<<<<<<< HEAD ======= <<<<<<< HEAD >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
rm(list = ls())

library(Lahman)
library(mosaic)
library(tidyr)
library(tidyverse)
library(dplyr)
library(mplot)
library(ggplot2)
library(cluster)
library(factoextra)
library(corrplot)
library(data.table)
library(mod)
library(modelr)
library(leaps)
library(caret)
library(ISLR2)
<<<<<<< HEAD
library(ggcorrplot)
library(glmnet)
======= library(ggcorrplot)
package 㤼㸱ggcorrplot㤼㸲 was built under R version 4.0.5
library(glmnet)
=======
rm(list = ls())

library(Lahman)
package 㤼㸱Lahman㤼㸲 was built under R version 4.0.5
library(mosaic)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'mosaic':
  method                           from   
  fortify.SpatialPolygonsDataFrame ggplot2

The 'mosaic' package masks several functions from core packages in order to add 
additional features.  The original behavior of these functions should not be affected by this.

Attaching package: 㤼㸱mosaic㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    count, do, tally

The following object is masked from 㤼㸱package:Matrix㤼㸲:

    mean

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    stat

The following objects are masked from 㤼㸱package:stats㤼㸲:

    binom.test, cor, cor.test, cov, fivenum, IQR, median, prop.test, quantile, sd, t.test, var

The following objects are masked from 㤼㸱package:base㤼㸲:

    max, mean, min, prod, range, sample, sum
library(tidyr)
package 㤼㸱tidyr㤼㸲 was built under R version 4.0.5
Attaching package: 㤼㸱tidyr㤼㸲

The following objects are masked from 㤼㸱package:Matrix㤼㸲:

    expand, pack, unpack
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages ----------------------------------------------------------------------------------- tidyverse 1.3.0 --
v tibble  3.1.0     v stringr 1.4.0
v readr   1.4.0     v forcats 0.5.0
v purrr   0.3.4     
package 㤼㸱tibble㤼㸲 was built under R version 4.0.5-- Conflicts -------------------------------------------------------------------------------------- tidyverse_conflicts() --
x mosaic::count()            masks dplyr::count()
x purrr::cross()             masks mosaic::cross()
x mosaic::do()               masks dplyr::do()
x tidyr::expand()            masks Matrix::expand()
x dplyr::filter()            masks stats::filter()
x ggstance::geom_errorbarh() masks ggplot2::geom_errorbarh()
x dplyr::lag()               masks stats::lag()
x tidyr::pack()              masks Matrix::pack()
x mosaic::stat()             masks ggplot2::stat()
x mosaic::tally()            masks dplyr::tally()
x tidyr::unpack()            masks Matrix::unpack()
library(dplyr)
library(mplot)
package 㤼㸱mplot㤼㸲 was built under R version 4.0.5
Attaching package: 㤼㸱mplot㤼㸲

The following object is masked from 㤼㸱package:mosaic㤼㸲:

    mplot
library(ggplot2)
library(cluster)
library(factoextra)
>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
package 㤼㸱factoextra㤼㸲 was built under R version 4.0.5Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(corrplot)
corrplot 0.92 loaded
library(data.table)
package 㤼㸱data.table㤼㸲 was built under R version 4.0.5Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.0 using 4 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: 㤼㸱data.table㤼㸲

The following object is masked from 㤼㸱package:purrr㤼㸲:

    transpose

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    between, first, last
library(mod)
package 㤼㸱mod㤼㸲 was built under R version 4.0.5
Attaching package: 㤼㸱mod㤼㸲

The following object is masked from 㤼㸱package:Matrix㤼㸲:

    drop

The following object is masked from 㤼㸱package:base㤼㸲:

    drop
library(modelr)

Attaching package: 㤼㸱modelr㤼㸲

The following object is masked from 㤼㸱package:mosaic㤼㸲:

    resample

The following object is masked from 㤼㸱package:ggformula㤼㸲:

    na.warn
>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf
#Load in People, Batting, and Pitching Dataframes
data("People") 
data("Batting")
data("Pitching")
#Looking at vars in all data frames 
names(People)
 [1] "playerID"     "birthYear"    "birthMonth"   "birthDay"     "birthCountry" "birthState"  
 [7] "birthCity"    "deathYear"    "deathMonth"   "deathDay"     "deathCountry" "deathState"  
[13] "deathCity"    "nameFirst"    "nameLast"     "nameGiven"    "weight"       "height"      
[19] "bats"         "throws"       "debut"        "finalGame"    "retroID"      "bbrefID"     
[25] "deathDate"    "birthDate"   
names(Batting)
 [1] "playerID" "yearID"   "stint"    "teamID"   "lgID"     "G"        "AB"       "R"       
 [9] "H"        "X2B"      "X3B"      "HR"       "RBI"      "SB"       "CS"       "BB"      
[17] "SO"       "IBB"      "HBP"      "SH"       "SF"       "GIDP"    
names(Pitching)
 [1] "playerID" "yearID"   "stint"    "teamID"   "lgID"     "W"        "L"        "G"       
 [9] "GS"       "CG"       "SHO"      "SV"       "IPouts"   "H"        "ER"       "HR"      
[17] "BB"       "SO"       "BAOpp"    "ERA"      "IBB"      "WP"       "HBP"      "BK"      
[25] "BFP"      "GF"       "R"        "SH"       "SF"       "GIDP"    
#Looking at years 
Pitching%>%
 arrange(yearID) 
#Merges player name to Batting data. 
bstats <- battingStats()
    str(bstats)
'data.frame':   108789 obs. of  29 variables:
 $ playerID: chr  "abercda01" "addybo01" "allisar01" "allisdo01" ...
 $ yearID  : int  1871 1871 1871 1871 1871 1871 1871 1871 1871 1871 ...
 $ stint   : int  1 1 1 1 1 1 1 1 1 1 ...
 $ teamID  : Factor w/ 149 levels "ALT","ANA","ARI",..: 136 111 39 142 111 56 111 24 56 24 ...
 $ lgID    : Factor w/ 7 levels "AA","AL","FL",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ G       : int  1 25 29 27 25 12 1 31 1 18 ...
 $ AB      : int  4 118 137 133 120 49 4 157 5 86 ...
 $ R       : int  0 30 28 28 29 9 0 66 1 13 ...
 $ H       : int  0 32 40 44 39 11 1 63 1 13 ...
 $ X2B     : int  0 6 4 10 11 2 0 10 1 2 ...
 $ X3B     : int  0 0 5 2 3 1 0 9 0 1 ...
 $ HR      : int  0 0 0 2 0 0 0 0 0 0 ...
 $ RBI     : int  0 13 19 27 16 5 2 34 1 11 ...
 $ SB      : int  0 8 3 1 6 0 0 11 0 1 ...
 $ CS      : int  0 1 1 1 2 1 0 6 0 0 ...
 $ BB      : int  0 4 2 0 2 0 1 13 0 0 ...
 $ SO      : int  0 0 5 2 1 1 0 1 0 0 ...
 $ IBB     : int  NA NA NA NA NA NA NA NA NA NA ...
 $ HBP     : int  NA NA NA NA NA NA NA NA NA NA ...
 $ SH      : int  NA NA NA NA NA NA NA NA NA NA ...
 $ SF      : int  NA NA NA NA NA NA NA NA NA NA ...
 $ GIDP    : int  0 0 1 0 0 0 0 1 0 0 ...
 $ BA      : num  0 0.271 0.292 0.331 0.325 0.224 0.25 0.401 0.2 0.151 ...
 $ PA      : num  4 122 139 133 122 49 5 170 5 86 ...
 $ TB      : num  0 38 54 64 56 15 1 91 2 17 ...
 $ SlugPct : num  0 0.322 0.394 0.481 0.467 0.306 0.25 0.58 0.4 0.198 ...
 $ OBP     : num  0 0.295 0.302 0.331 0.336 0.224 0.4 0.447 0.2 0.151 ...
 $ OPS     : num  0 0.617 0.696 0.812 0.803 ...
 $ BABIP   : num  0 0.271 0.303 0.326 0.328 0.229 0.25 0.404 0.2 0.151 ...
    

People$name <- paste(People$nameFirst, People$nameLast, sep = " ")

batting_name <- merge(Batting,
                 People[,c("playerID", "name")],
                 by = "playerID", all.x = TRUE)

#Merges player name to Pitching data.

People$name <- paste(People$nameFirst, People$nameLast, sep = " ")

pitching_name <- merge(Pitching,
                 People[,c("playerID", "name")],
                 by = "playerID", all.x = TRUE)
#Creating additional stats for bstats
bstats[is.na(bstats)] = 0
#is.nan(bstats)

bstats <- bstats %>%
  mutate(K_Percent = SO / PA) %>%
  mutate(BB_Percent = (BB + IBB) / PA) %>%
  mutate_all(~replace(., is.nan(.), 0))
invalid factor level, NA generatedinvalid factor level, NA generated
bstats <- bstats %>%
  mutate_at(vars(K_Percent, BB_Percent), funs(round(., 3)))
`funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas: 

  # Simple named list: 
  list(mean = mean, median = median)

  # Auto named with `tibble::lst()`: 
  tibble::lst(mean, median)

  # Using lambdas
  list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
bstats_salary <- bstats %>%
              filter(yearID >= 1985) %>%
              left_join(select(Salaries, playerID, yearID, teamID, salary), 
                         by=c("playerID", "yearID", "teamID"))

bstats_salary[is.na(bstats_salary)] = 0
str(bstats_salary)
'data.frame':   46535 obs. of  32 variables:
 $ playerID  : chr  "aasedo01" "abregjo01" "ackerji01" "adamsri02" ...
 $ yearID    : num  1985 1985 1985 1985 1985 ...
 $ stint     : num  1 1 1 1 1 1 1 1 1 1 ...
 $ teamID    : Factor w/ 149 levels "ALT","ANA","ARI",..: 5 35 134 117 33 102 94 134 134 134 ...
 $ lgID      : Factor w/ 7 levels "AA","AL","FL",..: 2 5 2 5 2 5 5 2 2 2 ...
 $ G         : num  54 6 61 54 54 91 22 12 36 14 ...
 $ AB        : num  0 9 0 121 0 165 36 20 0 34 ...
 $ R         : num  0 0 0 12 0 27 1 2 0 2 ...
 $ H         : num  0 0 0 23 0 46 10 4 0 4 ...
 $ X2B       : num  0 0 0 3 0 7 2 1 0 1 ...
 $ X3B       : num  0 0 0 1 0 3 0 0 0 0 ...
 $ HR        : num  0 0 0 2 0 6 0 1 0 0 ...
 $ RBI       : num  0 1 0 10 0 21 2 5 0 3 ...
 $ SB        : num  0 0 0 1 0 1 0 0 0 0 ...
 $ CS        : num  0 0 0 1 0 0 0 0 0 0 ...
 $ BB        : num  0 0 0 5 0 22 1 3 0 0 ...
 $ SO        : num  0 2 0 23 0 26 5 6 0 10 ...
 $ IBB       : num  0 0 0 3 0 5 0 0 0 0 ...
 $ HBP       : num  0 0 0 1 0 6 0 0 0 0 ...
 $ SH        : num  0 0 0 3 0 4 7 0 0 0 ...
 $ SF        : num  0 0 0 0 0 3 0 1 0 0 ...
 $ GIDP      : num  0 0 0 2 0 7 1 1 0 1 ...
 $ BA        : num  0 0 0 0.19 0 0.279 0.278 0.2 0 0.118 ...
 $ PA        : num  0 9 0 130 0 200 44 24 0 34 ...
 $ TB        : num  0 0 0 34 0 77 12 8 0 5 ...
 $ SlugPct   : num  0 0 0 0.281 0 0.467 0.333 0.4 0 0.147 ...
 $ OBP       : num  0 0 0 0.228 0 0.378 0.297 0.292 0 0.118 ...
 $ OPS       : num  0 0 0 0.509 0 0.845 0.63 0.692 0 0.265 ...
 $ BABIP     : num  0 0 0 0.219 0 0.294 0.323 0.214 0 0.167 ...
 $ K_Percent : num  0 0.222 0 0.177 0 0.13 0.114 0.25 0 0.294 ...
 $ BB_Percent: num  0 0 0 0.062 0 0.135 0.023 0.125 0 0 ...
 $ salary    : num  0 0 170000 0 147500 ...
bstats_sure <- bstats_salary %>%
  filter(PA > 150) %>%
  select(OPS, BABIP, K_Percent, BB_Percent, salary)

Data Preparation (Lesson 1 & 2)

#Keep players with over 150 at bats. (We can change this value if necessary).
#Creating batting average variable.

batting1 <- bstats %>%
  filter(AB >= 150)
  
bstats %>%
  filter(playerID == "bogaexa01")
<<<<<<< HEAD ======= <<<<<<< HEAD ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Exploratory Analysis (Lesson 1 & 2)

Lessons 1 and 2 will just be parts of the overall project. Simple things like data manipulation, apply functions, boxplots, etc. This will be data preparation items and exploratory analysis.

b <- ggplot(batting1, aes(x = teamID, y = HR)) +
  geom_boxplot(col = "black", aes(fill = teamID))
b
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
hitters1 <- batting1 %>%
  filter(yearID < 1895) %>%
  select(SlugPct)

hitters2 <- batting1 %>%
  filter(yearID > 1894, yearID < 1921) %>%
  select(SlugPct)

hitters3 <- batting1 %>%
  filter(yearID > 1920, yearID < 1969) %>%
  select(SlugPct)

hitters4 <- batting1 %>%
  filter(yearID > 1969) %>%
  select(SlugPct)
#Organizing 4 different datasets looking at slugging percentage for the following boxplots. All of these are somewhat different eras, with the most dramatic split being from before 1920 (pre-Babe Ruth) and after 1920 (during and post-Babe Ruth)
boxplot(hitters1,
        main = "Slugging percentage from late 1871 - 1894",
        ylab = "Slugging percentage",
        col = "blue",
        horizontal = TRUE)
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
boxplot(hitters2, 
        main = "Slugging percentage from 1895-1920",
        ylab = "Slugging percentage",
        col = "yellow",
        horizontal = TRUE)
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
boxplot(hitters3, 
        main = "Slugging percentage from 1921-1968",
        ylab = "Slugging percentage",
        col = "red",
        horizontal = TRUE)
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
boxplot(hitters4, 
        main = "Slugging percentage from 1969 - present",
        ylab = "Slugging percentage",
        col = "red",
        horizontal = TRUE)
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
sapply(hitters1, mean, na.rm = T)
  SlugPct 
0.3456088 
sapply(hitters2, mean, na.rm = T)
 SlugPct 
0.348923 
sapply(hitters3, mean, na.rm = T)
  SlugPct 
0.3972127 
sapply(hitters4, mean, na.rm = T)
  SlugPct 
0.4088045 
#Notice that gigantic increase between hitters2 and hitters3
summary(hitters2)
    SlugPct      
 Min.   :0.1480  
 1st Qu.:0.3003  
 Median :0.3430  
 Mean   :0.3489  
 3rd Qu.:0.3910  
 Max.   :0.8490  
summary(hitters3)
    SlugPct      
 Min.   :0.1760  
 1st Qu.:0.3420  
 Median :0.3900  
 Mean   :0.3972  
 3rd Qu.:0.4440  
 Max.   :0.8460  
summary(hitters4)
    SlugPct      
 Min.   :0.1730  
 1st Qu.:0.3540  
 Median :0.4040  
 Mean   :0.4088  
 3rd Qu.:0.4580  
 Max.   :0.8630  
summary(hitters4)
    SlugPct      
 Min.   :0.1730  
 1st Qu.:0.3540  
 Median :0.4040  
 Mean   :0.4088  
 3rd Qu.:0.4580  
 Max.   :0.8630  
#Keep batting stats that we want for pairs.
batting_num <- bstats %>%
  filter(PA >= 150) %>%
  select("BA", 'OBP', 'SlugPct', "SO", "BB", "HR")
  
careerBatting <- na.omit(bstats)
<<<<<<< HEAD <<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf

Career Batting Stats

careerBatting <- na.omit(bstats)
careerBatting <- careerBatting %>%
  select(playerID, BA, PA, SlugPct, OBP, SO, HR) %>%
  group_by(playerID) %>%
  summarise_all('mean')
careerBatting_num <- careerBatting %>%
  filter(PA >= 150) %>%
  select(BA, PA, SlugPct, OBP, SO, HR)

pairs(careerBatting_num)
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
corrmatrix <- cor(batting_num)
corrplot(corrmatrix, method = 'number') #Gives us correlation from pairs graph.
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
careerBatting_num1 <- careerBatting_num %>%
  filter(PA > 500)

0-dimensional Reduction (Lesson 4)

Bootstrapping

PCA (Lesson 4)

res <- batting_num %>% prcomp(scale = TRUE)
res
Standard deviations (1, .., p=6):
[1] 1.8624983 1.1955799 0.8163046 0.5272521 0.3234188 0.2296540

Rotation (n x k) = (6 x 6):
               PC1         PC2         PC3         PC4        PC5          PC6
BA      -0.3736490  0.53149382  0.20948811 -0.39409469  0.6134310  0.049063667
OBP     -0.4412694  0.38795844 -0.30295510 -0.06651166 -0.5817204  0.469217735
SlugPct -0.4816546  0.08527252  0.45916589  0.20230952 -0.3441137 -0.624948649
SO      -0.2974863 -0.61917967  0.04176753 -0.71554909 -0.1194610  0.009617743
BB      -0.4043725 -0.14520286 -0.75150469  0.19652707  0.2909420 -0.356888661
HR      -0.4262175 -0.39403532  0.29495049  0.49870136  0.2607132  0.509317820
loadings <- res$rotation
loadings
               PC1         PC2         PC3         PC4        PC5          PC6
BA      -0.3736490  0.53149382  0.20948811 -0.39409469  0.6134310  0.049063667
OBP     -0.4412694  0.38795844 -0.30295510 -0.06651166 -0.5817204  0.469217735
SlugPct -0.4816546  0.08527252  0.45916589  0.20230952 -0.3441137 -0.624948649
SO      -0.2974863 -0.61917967  0.04176753 -0.71554909 -0.1194610  0.009617743
BB      -0.4043725 -0.14520286 -0.75150469  0.19652707  0.2909420 -0.356888661
HR      -0.4262175 -0.39403532  0.29495049  0.49870136  0.2607132  0.509317820
score_mat <- res$x
score_mat
                   PC1           PC2           PC3           PC4           PC5           PC6
    [1,] -2.416723e+00  4.560698e+00  1.443027e+00 -7.333664e-01 -4.234072e-01 -1.762980e-01
    [2,]  1.219725e+00  1.849015e+00  8.201252e-01 -1.952915e-01  3.981469e-01  1.822513e-01
    [3,]  1.474218e+00  7.482123e-01  9.141729e-01  8.396478e-01 -2.439173e-01 -5.416897e-01
    [4,]  6.203888e-01  2.304795e+00  1.057469e+00 -2.640564e-01  2.662469e-01  3.072002e-02
    [5,]  2.943669e+00  3.660013e-01  5.506029e-01  4.155864e-01  5.317398e-01 -3.286813e-02
    [6,]  1.777087e+00  1.308355e+00  8.996221e-01  1.318660e-01  3.669270e-01 -1.200040e-01
    [7,]  1.638294e+00  1.365860e+00  9.687942e-01  2.460817e-01  2.518894e-01 -2.846689e-01
    [8,]  1.277859e+00  1.429171e+00  1.237701e+00  3.160011e-01  2.384888e-01 -3.187137e-01
    [9,]  2.575716e+00  7.738965e-01  5.169331e-01  3.002796e-01  5.345135e-01  1.057655e-01
   [10,]  1.406601e+00  1.626801e+00  1.019207e+00  6.878197e-02  3.105486e-01 -1.622986e-01
   [11,]  2.314598e+00  1.032260e+00  3.284764e-01  1.875309e-01  4.737664e-01  3.377658e-01
   [12,] -2.254698e+00  4.915125e+00  1.951355e+00 -1.215630e+00  1.700315e-01  1.075539e-01
   [13,]  1.714346e+00  1.191014e+00  1.054853e+00  3.211466e-01  2.940316e-01 -2.832409e-01
   [14,]  4.214521e+00 -5.515752e-01  3.050290e-01  7.087223e-01  7.976724e-01  3.980669e-02
   [15,]  2.271122e+00  1.078424e+00  5.187903e-01  1.175299e-01  5.660790e-01  2.481744e-01
   [16,]  7.655863e-01  2.041193e+00  1.014612e+00  1.844765e-02  5.616512e-02 -1.959685e-01
   [17,]  1.520407e+00  1.432379e+00  1.091449e+00  2.042299e-01  2.334932e-01 -3.524935e-01
   [18,]  1.490633e+00  1.291377e+00  6.930873e-01  3.470345e-01  6.483829e-02 -9.133176e-02
   [19,] -1.993183e-01  3.201744e+00  1.191853e+00 -5.892269e-01  4.491340e-01  4.036008e-01
   [20,]  3.770710e-01  2.434379e+00  7.232593e-01 -1.258865e-01  2.812814e-02  1.074989e-01
   [21,]  2.922852e-01  2.390471e+00  1.332478e+00 -8.020927e-02  1.240978e-01 -2.261130e-01
   [22,]  7.804409e-01  2.075181e+00  2.583384e-01 -8.693810e-02  3.394759e-03  4.109240e-01
   [23,]  1.371866e+00  9.825359e-01  9.688047e-01  7.256051e-01 -2.492550e-01 -5.812617e-01
   [24,] -2.382359e+00  4.714902e+00  1.062824e+00 -1.046896e+00 -3.540856e-02  3.003221e-01
   [25,]  1.292267e+00  2.096809e+00  6.511071e-01 -4.066068e-01  6.834969e-01  5.933871e-01
   [26,] -2.777582e+00  4.944257e+00  1.755964e+00 -1.083355e+00 -5.785753e-02  1.077638e-02
   [27,]  1.190319e+00  1.795224e+00  7.511231e-01 -9.836268e-02  3.912924e-01  6.458790e-02
   [28,]  2.138132e+00  7.503777e-01  5.815927e-01  2.363811e-01  3.601793e-01  5.370821e-02
   [29,]  2.204313e+00  9.435450e-01  5.069415e-01  1.122817e-01  4.312682e-01  1.689245e-01
   [30,]  2.534510e+00  9.701706e-01  6.262459e-01  7.652271e-02  7.558703e-01  2.656094e-01
   [31,]  1.554444e+00  1.436907e+00  1.008768e+00  9.023136e-02  5.609106e-01  1.073257e-01
   [32,]  1.819823e+00  1.362150e+00  6.227748e-01  4.177417e-02  4.474395e-01  1.647032e-01
   [33,]  3.601595e+00 -6.392722e-01  4.603145e-01  4.955963e-01  5.099287e-01 -2.749128e-01
   [34,]  2.645202e-01  2.481165e+00  9.207404e-01 -6.058332e-01  4.796779e-01  3.919094e-01
   [35,]  3.421297e+00  1.147581e-02  4.038722e-01  5.460176e-01  6.062009e-01  1.169545e-02
   [36,]  2.471482e-01  2.481274e+00  8.898948e-01 -5.414952e-01  3.639352e-01  1.736046e-01
   [37,]  2.150533e+00  1.295666e+00  5.544389e-01  1.153722e-02  6.516006e-01  3.546918e-01
   [38,]  3.006876e+00  8.594070e-03  8.192747e-01  5.894401e-01  4.886067e-01 -3.422591e-01
   [39,]  1.854183e-02  2.884613e+00  1.174663e+00 -5.676400e-01  3.734326e-01  1.501689e-01
   [40,]  1.393717e+00  1.754510e+00  7.957141e-01 -1.746703e-01  5.928169e-01  3.670016e-01
   [41,]  2.260195e+00  6.986164e-01  1.076252e+00  4.301822e-01  3.090228e-01 -5.521915e-01
   [42,]  5.987150e-02  2.642965e+00  1.483975e+00 -2.125679e-01  2.386474e-01 -2.420331e-01
   [43,]  4.316153e-01  2.249363e+00  8.628850e-01 -2.927017e-01  3.697471e-01  1.355797e-01
   [44,]  1.114305e+00  1.925993e+00  7.971480e-01 -1.876282e-01  4.587106e-01  1.283862e-01
   [45,]  1.854586e-01  2.651860e+00  1.294539e+00 -4.079149e-01  5.125728e-01  2.486702e-01
   [46,]  1.893873e-01  2.772122e+00  1.357466e+00 -4.803023e-01  5.973779e-01  3.360247e-01
   [47,]  7.292379e-01  1.737208e+00 -2.609344e-01 -9.363625e-02 -4.368283e-02  4.379741e-01
   [48,]  1.847550e+00  1.276145e+00  7.167369e-01 -2.892983e-02  5.097654e-01  1.042807e-01
   [49,]  3.626601e+00 -8.547987e-02  2.693330e-01  4.713822e-01  7.559704e-01  1.828194e-01
   [50,]  1.930785e+00  1.394545e+00  6.893944e-01 -6.183811e-02  6.532000e-01  2.401690e-01
   [51,] -6.078538e-02  3.176777e+00  1.211221e+00 -6.759564e-01  4.986540e-01  3.306064e-01
   [52,]  2.339012e+00  6.987610e-01  1.334819e-01  2.047737e-01  4.287504e-01  2.192671e-01
   [53,]  9.842678e-01  2.225258e+00  1.096110e+00 -3.051193e-01  5.516512e-01  1.454291e-01
   [54,]  1.455407e+00  1.672343e+00  9.417622e-01 -6.577560e-02  4.895289e-01 -1.238487e-03
   [55,]  4.300761e+00 -9.084043e-01  2.143078e-01  9.553783e-01  6.595707e-01 -6.440636e-02
   [56,]  4.710233e-01  1.423581e+00  1.662245e+00  4.631328e-01  2.677690e-01 -3.133157e-01
   [57,]  1.649192e+00  1.423337e+00  1.162990e+00  7.234994e-02  5.394208e-01 -1.026508e-01
   [58,]  2.768852e+00  1.478174e-01  8.899297e-01  5.451073e-01  3.915213e-01 -3.815478e-01
   [59,]  2.099573e+00  1.023482e+00  9.221362e-01  1.216150e-01  6.103257e-01  1.984430e-02
   [60,]  1.569637e+00  1.275754e+00  1.234741e+00 -7.314692e-03  4.644239e-01 -2.085609e-01
   [61,] -1.498821e-01  3.080767e+00  1.334832e+00 -5.264526e-01  3.427686e-01  4.359203e-02
   [62,]  2.568969e+00  9.856887e-01  6.948187e-01  8.865470e-02  7.938021e-01  2.354448e-01
   [63,]  1.673655e+00  9.690939e-01  8.796657e-01  1.193615e-01  4.153881e-01 -3.410592e-02
   [64,] -4.853341e-02  2.629401e+00  1.554874e+00 -1.519071e-01  2.415414e-01 -2.272155e-01
   [65,]  2.410371e+00  7.924908e-01  2.061873e-01  2.658986e-01  4.473866e-01  2.400031e-01
   [66,]  2.280413e+00  9.146890e-01  8.091815e-01  2.796219e-01  4.894963e-01 -1.584045e-01
   [67,] -2.505357e-01  3.082187e+00  1.431683e+00 -4.758327e-01  3.200074e-01  8.442382e-02
   [68,] -1.108737e+00  4.083915e+00  1.210488e+00 -1.059773e+00  4.674161e-01  5.476804e-01
   [69,]  2.146383e+00  1.108095e+00  5.400660e-01  1.272634e-01  6.767289e-01  3.062165e-01
   [70,] -3.332913e+00  5.029997e+00  1.529292e+00 -8.384134e-01 -1.736625e-01 -2.189377e-01
   [71,]  1.917417e+00  1.118149e+00  1.174363e+00  2.949981e-01  3.501859e-01 -4.599910e-01
   [72,]  2.510081e+00  4.956159e-01  4.078296e-01  5.372300e-01  4.147258e-01 -5.399929e-02
   [73,]  1.842099e+00  1.296739e+00  6.460042e-01 -8.950588e-02  5.084560e-01  2.165966e-01
   [74,]  1.946117e+00  1.088249e+00  9.342168e-01  1.443770e-01  5.197305e-01 -4.137615e-02
   [75,]  4.010638e+00 -9.043144e-01 -9.277337e-02  5.143939e-01  5.910971e-01  1.226830e-01
   [76,]  2.317837e+00  5.746190e-01  5.556606e-01  4.191115e-01  4.862667e-01  5.763530e-02
   [77,]  3.074563e-01  2.534392e+00  1.401686e+00 -3.824038e-01  4.268553e-01 -1.232876e-03
   [78,]  1.167005e+00  1.809348e+00  1.129422e+00 -4.721470e-02  4.501069e-01 -2.529551e-02
   [79,]  1.632560e+00  1.468100e+00  9.918127e-01  1.531525e-03  4.588732e-01 -9.019922e-02
   [80,]  2.741739e+00  5.302697e-01  3.604595e-01  2.144569e-01  5.750893e-01  2.100966e-01
   [81,]  1.971533e+00  1.017793e+00  9.299388e-01  1.804371e-01  6.125357e-01  6.301301e-02
   [82,]  2.721711e+00  2.680274e-01  2.327942e-02  2.907707e-01  3.877542e-01  2.068869e-01
   [83,]  2.135547e-01  2.706228e+00  1.040692e+00 -4.148453e-01  3.578101e-01  1.113258e-01
   [84,]  2.376955e+00  6.755834e-01  6.517979e-01  1.401077e-01  4.918054e-01 -3.603275e-02
   [85,]  2.360438e+00  7.127484e-01  6.694583e-01  2.299599e-01  5.813277e-01  5.283155e-02
   [86,]  4.128479e-02  2.776277e+00  1.415481e+00 -3.831971e-01  3.556296e-01 -7.593776e-03
   [87,] -4.389638e-01  3.392092e+00  8.501625e-01 -7.063879e-01  3.920052e-01  4.741925e-01
   [88,]  1.770532e+00  1.189871e+00  1.037435e+00  1.423073e-01  4.706187e-01 -1.423005e-01
   [89,]  1.930187e+00  9.620627e-01  7.382488e-01  2.714791e-01  3.795639e-01 -9.154777e-02
   [90,]  2.155863e+00  9.065004e-01  8.945369e-01  3.965488e-01  4.249762e-01 -1.818956e-01
   [91,]  1.523907e-01  2.862417e+00  1.276905e+00 -4.713282e-01  3.751188e-01  9.063007e-02
   [92,]  9.995124e-01  1.823088e+00  1.170911e+00  1.344113e-02  4.476761e-01 -1.903802e-02
   [93,]  1.110998e+00  2.110401e+00  9.938894e-01 -2.666306e-01  5.675575e-01  1.759913e-01
   [94,]  5.192421e-01  2.435532e+00  1.302713e+00 -3.091739e-01  4.550121e-01  7.071398e-02
   [95,]  7.936573e-01  2.224945e+00  1.313504e+00 -3.269706e-01  4.517846e-01 -6.770236e-02
   [96,]  8.403641e-01  2.256260e+00  1.178937e+00 -2.087666e-01  4.417500e-01 -3.706420e-02
   [97,]  1.148718e+00  1.669228e+00  2.253819e-02 -2.459589e-01  2.848365e-01  5.532400e-01
   [98,]  1.185487e+00  1.572026e+00  3.058708e-01 -8.272972e-02  2.987945e-01  1.777574e-01
   [99,]  2.380042e+00  6.606109e-01  7.417901e-01 -1.160135e-01  6.060816e-01  9.513828e-02
  [100,]  3.908648e+00 -6.824891e-01 -8.243134e-02  8.576197e-01  4.371080e-01 -5.428605e-02
  [101,]  2.174089e+00  1.264951e+00  6.906613e-01  2.511012e-02  7.083800e-01  2.293995e-01
  [102,]  1.618655e+00  1.738117e+00  8.890477e-01 -1.790972e-01  6.765123e-01  2.320327e-01
  [103,]  1.964422e+00  1.146938e+00  4.015434e-01  6.802530e-02  4.616389e-01  2.143541e-01
  [104,] -1.042642e+00  3.631385e+00  1.599374e+00 -6.467583e-01  2.788696e-01  1.557212e-01
  [105,] -3.249017e-01  2.867747e+00  1.670345e+00 -2.033250e-01  3.077568e-01 -1.065481e-01
  [106,]  1.571414e-01  2.589093e+00  1.581907e+00 -1.917588e-01  1.676164e-01 -4.610063e-01
  [107,]  3.075156e+00 -2.184416e-01  1.588215e-01  3.996932e-01  3.985028e-01  1.536229e-01
  [108,]  9.464263e-01  2.334568e+00  9.881629e-01 -4.426485e-01  6.270796e-01  3.568946e-01
  [109,] -6.112114e-01  3.051586e+00  8.299057e-01 -3.936699e-01  1.653944e-01  1.061102e-01
  [110,] -2.891211e-01  3.207652e+00  1.054573e+00 -6.829069e-01  3.826751e-01  3.203025e-01
  [111,]  1.958538e+00  1.147893e+00  4.340068e-01  1.390249e-01  5.734960e-01  2.825576e-01
  [112,]  8.340147e-02  2.055687e+00  1.394886e+00  1.639048e-01  1.670183e-01 -3.031638e-01
  [113,]  1.948431e+00  1.402737e+00  5.745996e-01 -8.495996e-02  6.732018e-01  3.401546e-01
  [114,]  1.331906e+00  1.598962e+00  1.169111e+00  7.239512e-02  4.155062e-01 -1.724547e-01
  [115,]  2.089271e+00  8.270733e-01  9.166172e-01  3.041473e-01  5.516338e-01 -6.825203e-02
  [116,]  6.652700e-01  2.346548e+00  1.092434e+00 -3.183514e-01  5.451402e-01  2.086985e-01
  [117,]  2.182842e+00  9.434587e-01  7.752312e-01  3.309184e-01  5.282321e-01 -5.022710e-02
  [118,]  5.013390e-01  2.533947e+00  1.210166e+00 -3.879506e-01  4.280099e-01  5.845775e-02
  [119,]  2.398461e+00  5.670894e-01  6.248191e-01  2.635547e-01  5.100397e-01  1.409121e-03
  [120,] -1.188190e+00  3.900769e+00  1.819585e+00 -8.126923e-01  3.070541e-01  4.488749e-02
  [121,]  2.227782e+00  1.044966e+00  9.926182e-01  1.859686e-01  5.704792e-01 -1.576408e-01
  [122,]  6.265958e-01  2.374716e+00  7.351219e-01 -2.704773e-01  3.419254e-01  2.442308e-01
  [123,] -1.527206e+00  3.792398e+00  1.498283e+00 -5.826627e-01  2.284069e-01  1.143657e-01
  [124,]  1.949358e+00  7.736311e-01  4.591902e-01  4.113739e-01  3.819606e-01  2.007939e-02
  [125,]  9.546985e-01  1.712587e+00  1.279208e+00  6.244127e-02  3.509531e-01 -2.032127e-01
  [126,]  4.175919e+00 -6.018102e-01  3.044794e-01  5.929268e-01  8.285393e-01  6.653842e-02
  [127,]  3.073146e+00  2.745347e-01  7.352831e-01  4.814719e-01  5.952238e-01 -1.992386e-01
  [128,]  1.774820e+00  1.289509e+00  6.669919e-01 -1.641910e-02  5.258865e-01  6.206168e-02
  [129,]  5.375029e-01  2.595559e+00  9.792746e-01 -4.384009e-01  5.128877e-01  2.760494e-01
  [130,]  1.598670e+00  1.663336e+00  8.385291e-01 -1.327358e-01  5.606892e-01  2.006034e-01
  [131,]  8.938875e-02  2.782653e+00  9.391116e-01 -4.292095e-01  3.250307e-01  1.562155e-01
  [132,]  4.491808e+00 -1.287511e+00  3.988355e-01  6.978455e-01  6.750664e-01 -2.784215e-01
  [133,]  3.277880e+00 -6.584339e-02  6.927470e-01  4.305486e-01  6.061131e-01 -2.223229e-01
  [134,]  1.638951e+00  1.263582e+00  1.160531e+00  2.927038e-01  3.091054e-01 -3.312571e-01
  [135,]  3.296838e+00  2.304245e-01  3.456176e-01  2.485582e-01  8.001902e-01  3.026274e-01
  [136,]  3.596579e+00 -2.680050e-01  5.883358e-01  5.459397e-01  6.462194e-01 -1.850761e-01
  [137,]  2.454556e+00  6.178760e-01  7.683971e-01  3.774372e-01  4.885282e-01 -9.600194e-02
  [138,]  3.253124e+00  2.323717e-01  4.309048e-01  3.185377e-01  7.544745e-01  1.730422e-01
  [139,]  1.970733e+00  1.018884e+00  1.053743e+00  1.557218e-01  5.270654e-01 -1.585225e-01
  [140,]  1.732010e+00  1.305955e+00  9.698273e-01  4.194498e-02  5.546218e-01  9.694220e-03
  [141,]  2.225008e+00  7.309146e-01  6.902748e-01  3.084738e-02  4.856930e-01 -3.255164e-02
  [142,]  1.097909e+00  1.474785e+00  1.536971e+00  3.588217e-01  2.872577e-01 -4.562505e-01
  [143,] -2.784413e-01  2.874435e+00  1.589095e+00 -2.842018e-01  7.354918e-02 -4.702583e-01
  [144,]  3.543882e+00 -3.235219e-01  6.006674e-01  3.081664e-01  7.149754e-01 -8.164553e-02
  [145,]  2.129066e+00  8.346168e-01  6.714373e-01  2.156418e-01  6.212377e-01  1.639034e-01
  [146,]  2.778449e+00  4.690608e-01  5.346695e-01  3.530826e-01  5.238112e-01 -1.691195e-02
  [147,]  3.318391e+00 -4.019898e-02  1.329822e-01  4.554767e-01  5.679152e-01  1.507273e-01
  [148,]  1.961713e+00  1.228795e+00  6.940204e-01 -2.294416e-01  6.582778e-01  2.966505e-01
  [149,]  6.883506e-01  2.237150e+00  1.111198e+00 -1.600857e-01  3.408241e-01 -1.358345e-01
  [150,]  2.674405e+00  6.525884e-01  5.475495e-01  3.712414e-02  7.278302e-01  2.354851e-01
  [151,]  3.556008e+00 -2.199490e-01  4.501220e-01  4.201832e-01  7.066383e-01 -9.600422e-03
  [152,]  7.393203e-01  2.392853e+00  1.287022e+00 -3.290517e-01  4.924273e-01  1.329802e-02
  [153,]  1.280523e+00  2.026696e+00  8.107106e-01 -2.868386e-01  6.492289e-01  3.371576e-01
  [154,]  2.170348e+00  1.131354e+00  6.813562e-01 -6.638855e-02  6.787592e-01  2.330541e-01
  [155,]  1.849284e+00  9.991822e-01  5.051238e-01 -5.257306e-02  4.897946e-01  2.653435e-01
  [156,]  1.870168e+00  1.316393e+00  6.006543e-01 -4.324355e-02  5.540260e-01  2.129298e-01
  [157,]  1.371166e+00  1.486129e+00  1.384976e+00  2.654090e-01  3.073133e-01 -4.855113e-01
  [158,]  7.454876e-01  2.311675e+00  9.709886e-01 -3.586801e-01  4.676539e-01  1.803653e-01
  [159,]  3.140966e+00 -1.743634e-01  3.273602e-01  3.639460e-01  5.143199e-01 -9.705433e-02
  [160,]  2.111663e+00  1.092447e+00  5.673255e-01  4.419451e-02  5.741471e-01  1.651516e-01
  [161,]  2.319455e+00  8.086177e-01  7.777198e-01  3.865898e-01  5.497539e-01 -1.071935e-01
  [162,]  1.545696e+00  1.581049e+00  7.992864e-01 -1.243311e-01  5.378649e-01  1.187910e-01
  [163,]  3.098880e-01  2.733051e+00  1.364830e+00 -3.830859e-01  4.013289e-01 -2.839183e-02
  [164,]  1.053480e+00  2.035085e+00  1.117748e+00 -2.013981e-01  4.824652e-01 -2.245388e-02
  [165,]  3.807886e+00 -5.048465e-01  5.647328e-01  7.574360e-01  5.701567e-01 -3.459630e-01
  [166,]  2.855763e+00  5.998251e-01  4.149993e-01  3.069515e-01  6.704102e-01  1.883833e-01
 [ reached getOption("max.print") -- omitted 35229 rows ]
get_eig(res)
<<<<<<< HEAD ======= <<<<<<< HEAD ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Screeplot

get_eig(res) %>%
  ggplot(aes(x = 1:6, y = cumulative.variance.percent)) +
  geom_line() +
  geom_point() +
  geom_hline(yintercept = 80) +
  xlab("Principal Component") +
  ylab("Proportion of Variance Explained") +
  ggtitle("Scree Plot of Principal Component for Batting Statistics")
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

2 Principal Components: PC1 and PC2

fviz_screeplot(res, main = "Scree Plot")
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Can Identify an elbow in 3.

Biplot

res %>%
  fviz_pca_var(axes = c(1,2),
               col.var = "contrib",
               gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
               repel = TRUE
               )
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Cluster Analysis (Lesson 5)

#NOT COMPLETE!!!!! This was just a test, bstats is way too big.
bstats_best <- bstats %>%
  filter(PA >= 600)

eu_dist <- get_dist(careerBatting_num1, method = 'euclidean')
hc_complete <- hclust(eu_dist, method = 'complete')

plot(hc_complete)
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Silhouette

res_test <- careerBatting_num1 %>% kmeans(7)
  str(res_test)
List of 9
 $ cluster     : int [1:313] 6 1 4 3 3 3 2 2 4 6 ...
 $ centers     : num [1:7, 1:6] 0.274 0.282 0.28 0.279 0.295 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:7] "1" "2" "3" "4" ...
  .. ..$ : chr [1:6] "BA" "PA" "SlugPct" "OBP" ...
 $ totss       : num 651407
 $ withinss    : num [1:7] 15184 28979 12723 15413 13086 ...
 $ tot.withinss: num 110607
 $ betweenss   : num 540799
 $ size        : int [1:7] 50 102 44 36 33 21 27
 $ iter        : int 3
 $ ifault      : int 0
 - attr(*, "class")= chr "kmeans"
distance <- get_dist(careerBatting_num1, method = "euclidean")
sil <- silhouette(x = res_test$cluster, dist = distance)
summary(sil)
Silhouette of 313 units in 7 clusters from silhouette.default(x = res_test$cluster, dist = distance) :
 Cluster sizes and average silhouette widths:
       50       102        44        36        33        21        27 
0.3520849 0.4329740 0.3000351 0.2682495 0.3614668 0.4120772 0.3306556 
Individual silhouette widths:
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-0.06379  0.21423  0.38618  0.36465  0.51790  0.64837 
sil %>% head()
     cluster neighbor  sil_width
[1,]       6        5 0.35570879
[2,]       1        7 0.35948971
[3,]       4        6 0.21976316
[4,]       3        1 0.55018020
[5,]       3        4 0.08291147
[6,]       3        1 0.10924787
fviz_nbclust(careerBatting_num1, hcut, hc_method = "complete", hc_metric = "euclidean", method = "wss")
<<<<<<< HEAD ======= <<<<<<< HEAD >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
<<<<<<< HEAD

=======

=======

>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
fviz_nbclust(careerBatting_num1, hcut, hc_method = "complete", hc_metric = "euclidean", method = "wss")
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
##This is to test other values of K for the silhouette method.
res_test1 <- careerBatting_num1 %>% kmeans(10 )
  str(res_test1)
List of 9
 $ cluster     : int [1:313] 10 4 6 3 3 3 8 2 6 10 ...
 $ centers     : num [1:10, 1:6] 0.287 0.278 0.285 0.273 0.269 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:10] "1" "2" "3" "4" ...
  .. ..$ : chr [1:6] "BA" "PA" "SlugPct" "OBP" ...
 $ totss       : num 651407
 $ withinss    : num [1:10] 5561 3421 7533 8158 17850 ...
 $ tot.withinss: num 82705
 $ betweenss   : num 568701
 $ size        : int [1:10] 47 26 32 35 31 29 28 40 25 20
 $ iter        : int 4
 $ ifault      : int 0
 - attr(*, "class")= chr "kmeans"
distance <- get_dist(careerBatting_num1, method="euclidean")
sil <- silhouette(x = res_test1$cluster, dist = distance)
summary(sil)
Silhouette of 313 units in 10 clusters from silhouette.default(x = res_test1$cluster, dist = distance) :
 Cluster sizes and average silhouette widths:
       47        26        32        35        31        29        28        40        25 
0.4123528 0.2235291 0.3095730 0.3662893 0.2348064 0.2444163 0.3084443 0.2360885 0.4169711 
       20 
0.3504059 
Individual silhouette widths:
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-0.07461  0.18155  0.32364  0.31245  0.44921  0.62394 
sil %>% head()
     cluster neighbor  sil_width
[1,]      10        6 0.25143884
[2,]       4        8 0.56107068
[3,]       6       10 0.21097598
[4,]       3        2 0.37769870
[5,]       3        6 0.09750601
[6,]       3        4 0.41195414
fviz_silhouette(sil)
<<<<<<< HEAD ======= <<<<<<< HEAD ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Diana

Linear Regression (Lesson 6)

Linear Regression comparing team payroll and win rate.

teams = as.data.table(Teams)
teams = teams[, .(yearID,
                  lgID = as.character(lgID),
                  teamID = as.character(teamID),
                  franchID = as.character(franchID),
                  Rank, G, W, L, R, ERA, SO,
                  WinPercent = W/(W+L))]

salaries = as.data.table(Salaries)
salaries = salaries[, c("lgID", "teamID", "salary1M") :=
                      list(as.character(lgID), as.character(teamID), salary / 1e6L)]
payroll = salaries[, .(payroll = sum(salary1M)), by=.(teamID, yearID)]
teamPayroll = merge(teams, payroll, by = c("teamID", "yearID"))
<<<<<<< HEAD
ggplot(data = teamPayroll, aes(x = payroll, y = WinPercent)) + geom_point()  + labs(x = "Payroll (in millions)", y = "Win Percentage") +
  geom_smooth(method = lm, se = FALSE)
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf
mod_lm <- lm(data = teamPayroll, WinPercent~payroll)
mod_lm

Call:
lm(formula = WinPercent ~ payroll, data = teamPayroll)

Coefficients:
(Intercept)      payroll  
  0.4796007    0.0003396  
summary(mod_lm)

Call:
lm(formula = WinPercent ~ payroll, data = teamPayroll)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.230866 -0.048237 -0.000954  0.049584  0.211074 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.4796007  0.0037895 126.561  < 2e-16 ***
payroll     0.0003396  0.0000512   6.633 5.61e-11 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.06714 on 916 degrees of freedom
Multiple R-squared:  0.04583,   Adjusted R-squared:  0.04479 
F-statistic:    44 on 1 and 916 DF,  p-value: 5.611e-11
summary(mod_lm)

Call:
lm(formula = WinPercent ~ payroll, data = teamPayroll)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.230866 -0.048237 -0.000954  0.049584  0.211074 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.4796007  0.0037895 126.561  < 2e-16 ***
payroll     0.0003396  0.0000512   6.633 5.61e-11 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.06714 on 916 degrees of freedom
Multiple R-squared:  0.04583,   Adjusted R-squared:  0.04479 
F-statistic:    44 on 1 and 916 DF,  p-value: 5.611e-11
payroll_pred <- teamPayroll %>%
  add_predictions(mod_lm)

payroll_pred %>%
  filter(yearID >= 2010) %>%
  arrange(desc(pred)) %>%
  head(25)
<<<<<<< HEAD ======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
payroll_pred %>%
  filter(yearID >= 2010) %>%
  arrange(desc(WinPercent)) %>%
  head(25)
<<<<<<< HEAD ======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Only five teams are in the top 25 of both payroll and win percentage in the 2010s. These teams are the 2011 Phillies, 2011 Yankees, 2010 Yankees, 2012 Yankees, and 2016 Rangers. This shows that spending the most money doesn’t automatically mean you are getting the best product on the field. ## Simple Linear Regression

Multiple Linear Regression

bstats_salary <- bstats_salary %>%
  filter(PA >= 100) %>%
  filter(salary > 500000)
<<<<<<< HEAD
bstats_salary_21century <- bstats_salary %>%
  filter(yearID >= 2002)
lm_mod <- lm(salary ~ H, HR, data = bstats_salary_21century)
summary(lm_mod)

Call:
lm(formula = salary ~ H, data = bstats_salary_21century, subset = HR)

Residuals:
     Min       1Q   Median       3Q      Max 
-4454703 -1184411  -175489   774007 14030406 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -175015.7    82216.4  -2.129   0.0333 *  
H             39604.4      661.7  59.854   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2299000 on 3982 degrees of freedom
Multiple R-squared:  0.4736,    Adjusted R-squared:  0.4735 
F-statistic:  3583 on 1 and 3982 DF,  p-value: < 2.2e-16
lm_mod_prd <- bstats_salary_21century %>% add_predictions(lm_mod)
lm_mod_prd
=======
lm_mod_prd <- bstats_salary %>% add_predictions(lm_mod)
lm_mod_prd
<<<<<<< HEAD ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
full_model <- lm(salary ~., data = bstats_sure)
summary(full_model)

Call:
lm(formula = salary ~ ., data = bstats_sure)

Residuals:
     Min       1Q   Median       3Q      Max 
-6914779 -1878645 -1019496   403743 29613794 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -1794883     277282  -6.473 9.93e-11 ***
OPS           9325457     399105  23.366  < 2e-16 ***
BABIP       -10628363    1053976 -10.084  < 2e-16 ***
K_Percent    -3344230     512360  -6.527 6.95e-11 ***
BB_Percent    7390060     977602   7.559 4.31e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3549000 on 13381 degrees of freedom
Multiple R-squared:  0.08167,   Adjusted R-squared:  0.0814 
F-statistic: 297.5 on 4 and 13381 DF,  p-value: < 2.2e-16
full_model_pred <- bstats_salary_21century %>% add_predictions(full_model)
<<<<<<< HEAD =======
prediction from a rank-deficient fit may be misleading
full_model_pred
<<<<<<< HEAD ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815

Resampling Methods

franchise <- c(`ANA` = "LAA", `ARI` = "ARI", `ATL` = "ATL", 
               `BAL` = "BAL", `BOS` = "BOS", `CAL` = "LAA",
               `CHA` = "CHA", `CHN` = "CHN", `CIN` = "CIN", 
               `CLE` = "CLE", `COL` = "COL", `DET` = "DET", 
               `FLO` = "MIA", `HOU` = "HOU", `KCA` = "KCA", 
               `LAA` = "LAA", `LAN` = "LAN", `MIA` = "MIA", 
               `MIL` = "MIL", `MIN` = "MIN", `ML4` = "MIL", 
               `MON` = "WAS", `NYA` = "NYA", `NYM` = "NYN", 
               `NYN` = "NYN", `OAK` = "OAK", `PHI` = "PHI", 
               `PIT` = "PIT", `SDN` = "SDN", `SEA` = "SEA",
               `SFG` = "SFN", `SFN` = "SFN", `SLN` = "SLN", 
               `TBA` = "TBA", `TEX` = "TEX", `TOR` = "TOR",
               `WAS` = "WAS")
<<<<<<< HEAD ======= <<<<<<< HEAD >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
# Salary of hitters with best batting avg 
top_battingAVG <- bstats_salary_21century%>%
  select(BA, salary) %>%
  arrange(desc(BA))%>%
  head(1500)

  ggplot(data = top_battingAVG, aes(x = BA, y= salary)) +
    geom_point()+
    geom_smooth(method = lm) +
    labs(title="How Batting AVG affects Salary")

# setting seed to generate a reproducible random sampling
set.seed(123)
 
# defining training control as cross-validation and value of K equal to 10
train_control <- trainControl(method = "cv",
                              number = 10)

# training the model
model <- train(salary ~ OBP, data = bstats_salary_21century,
               method = "lm",
               trControl = train_control)

print(model)
=======
avg_team_salaries <- Salaries %>%
    group_by(yearID, franchise, lgID) %>%
    summarise(salary = mean(salary)/1e6) %>%
    filter(!(franchise == "CLE" & lgID == "NL"))
>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
`summarise()` has grouped output by 'yearID', 'franchise'. You can override using the `.groups` argument.

Feature Selection

<<<<<<< HEAD
#Correlation mapping 

#making correlation heat map 
corr_numeric <- round(cor(bstats_salary_numvars), 1)

#plot to visualize the correlations 
ggcorrplot(corr_numeric,
           type = "lower",
           lab = TRUE, 
           lab_size = 2,  
           colors = c("tomato2", "white", "springgreen3"),
           title="Correlogram of batting Data", 
           ggtheme=theme_bw)
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
regfit.full = regsubsets(salary ~., data = bstats_salary_numvars,  nvmax = 13, method="exhaustive")
3  linear dependencies found
Reordering variables and trying again:
summary(regfit.full)
Subset selection object
Call: regsubsets.formula(salary ~ ., data = bstats_salary_numvars, 
    nvmax = 13, method = "exhaustive")
26 Variables  (and intercept)
           Forced in Forced out
G              FALSE      FALSE
AB             FALSE      FALSE
R              FALSE      FALSE
H              FALSE      FALSE
X2B            FALSE      FALSE
X3B            FALSE      FALSE
HR             FALSE      FALSE
RBI            FALSE      FALSE
SB             FALSE      FALSE
CS             FALSE      FALSE
BB             FALSE      FALSE
SO             FALSE      FALSE
IBB            FALSE      FALSE
HBP            FALSE      FALSE
SH             FALSE      FALSE
SF             FALSE      FALSE
GIDP           FALSE      FALSE
BA             FALSE      FALSE
SlugPct        FALSE      FALSE
OBP            FALSE      FALSE
BABIP          FALSE      FALSE
K_Percent      FALSE      FALSE
BB_Percent     FALSE      FALSE
PA             FALSE      FALSE
TB             FALSE      FALSE
OPS            FALSE      FALSE
1 subsets of each size up to 14
Selection Algorithm: exhaustive
          G   AB  R   H   X2B X3B HR  RBI SB  CS  BB  SO  IBB HBP SH  SF  GIDP BA  PA  TB 
1  ( 1 )  " " " " " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
2  ( 1 )  " " " " " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
3  ( 1 )  "*" " " " " " " " " " " " " " " " " " " " " " " " " " " "*" " " " "  " " "*" " "
4  ( 1 )  "*" " " " " " " " " " " " " " " " " " " " " " " "*" " " "*" " " " "  " " "*" " "
5  ( 1 )  "*" " " " " " " " " "*" " " " " " " " " " " " " "*" " " "*" " " " "  " " "*" " "
6  ( 1 )  "*" " " " " " " "*" "*" " " " " " " " " " " " " "*" " " "*" " " " "  " " "*" " "
7  ( 1 )  "*" " " " " " " "*" "*" " " " " " " " " " " " " "*" " " "*" " " " "  " " "*" " "
8  ( 1 )  "*" " " " " " " "*" "*" " " " " " " " " " " " " "*" " " "*" " " "*"  " " "*" " "
9  ( 1 )  "*" " " " " " " "*" "*" " " " " " " " " " " " " "*" " " "*" " " "*"  " " "*" " "
10  ( 1 ) "*" " " " " " " "*" "*" " " " " " " " " " " " " "*" " " "*" " " "*"  " " "*" " "
11  ( 1 ) "*" " " " " " " "*" "*" " " " " "*" "*" " " " " "*" " " "*" " " "*"  " " "*" " "
12  ( 1 ) "*" " " " " " " "*" "*" " " " " "*" "*" " " " " "*" " " "*" " " "*"  " " "*" " "
13  ( 1 ) "*" " " " " " " "*" "*" " " "*" "*" "*" " " "*" "*" " " "*" " " "*"  " " "*" " "
14  ( 1 ) "*" "*" " " " " "*" "*" "*" "*" "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
          SlugPct OBP OPS BABIP K_Percent BB_Percent
1  ( 1 )  " "     " " " " " "   " "       " "       
2  ( 1 )  " "     " " " " " "   " "       "*"       
3  ( 1 )  " "     " " " " " "   " "       " "       
4  ( 1 )  " "     " " " " " "   " "       " "       
5  ( 1 )  " "     " " " " " "   " "       " "       
6  ( 1 )  " "     " " " " " "   " "       " "       
7  ( 1 )  " "     " " "*" " "   " "       " "       
8  ( 1 )  " "     " " "*" " "   " "       " "       
9  ( 1 )  "*"     " " " " " "   " "       "*"       
10  ( 1 ) "*"     " " " " " "   "*"       "*"       
11  ( 1 ) "*"     " " " " " "   " "       "*"       
12  ( 1 ) "*"     " " " " " "   "*"       "*"       
13  ( 1 ) "*"     " " " " " "   " "       "*"       
14  ( 1 ) " "     " " "*" "*"   " "       " "       
======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
summary(regfit.full)$rsq
 [1] 0.1735921 0.1997069 0.2379362 0.2627538 0.2763364 0.2820003 0.2891514 0.2937692 0.2962186
[10] 0.2979275 0.2997391 0.3013596 0.3020423 0.3031258
======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
plot(summary(regfit.full)$rsq)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
reg.summary <- summary(regfit.full) #get the summary

par(mfrow=c(2,2))
#rss plot -  NOT USEFUL
plot(reg.summary$rss ,xlab="Number of Variables ",ylab="RSS",type="l")

#adjr2 plot
plot(reg.summary$adjr2 ,xlab="Number of Variables ", ylab="Adjusted RSq",type="l")

max_adjr2 <- which.max(reg.summary$adjr2)
points(max_adjr2,reg.summary$adjr2[max_adjr2], col="red",cex=2,pch=20)

# AIC criterion (Cp) to minimize
plot(reg.summary$cp ,xlab="Number of Variables ",ylab="Cp", type='l')

min_cp <- which.min(reg.summary$cp )
points(min_cp, reg.summary$cp[min_cp],col="red",cex=2,pch=20)

# BIC criterion to minimize
plot(reg.summary$bic ,xlab="Number of Variables ",ylab="BIC",type='l')

min_bic <- which.min(reg.summary$bic)
points(min_bic,reg.summary$bic[min_bic],col="red",cex=2,pch=20)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
#Forward stepwise selection
regfit.fwd = regsubsets(salary ~. , data=bstats_salary_numvars, nvmax=13, method ="forward")
3  linear dependencies found
Reordering variables and trying again:
summary(regfit.fwd)
Subset selection object
Call: regsubsets.formula(salary ~ ., data = bstats_salary_numvars, 
    nvmax = 13, method = "forward")
26 Variables  (and intercept)
           Forced in Forced out
G              FALSE      FALSE
AB             FALSE      FALSE
R              FALSE      FALSE
H              FALSE      FALSE
X2B            FALSE      FALSE
X3B            FALSE      FALSE
HR             FALSE      FALSE
RBI            FALSE      FALSE
SB             FALSE      FALSE
CS             FALSE      FALSE
BB             FALSE      FALSE
SO             FALSE      FALSE
IBB            FALSE      FALSE
HBP            FALSE      FALSE
SH             FALSE      FALSE
SF             FALSE      FALSE
GIDP           FALSE      FALSE
BA             FALSE      FALSE
SlugPct        FALSE      FALSE
OBP            FALSE      FALSE
BABIP          FALSE      FALSE
K_Percent      FALSE      FALSE
BB_Percent     FALSE      FALSE
PA             FALSE      FALSE
TB             FALSE      FALSE
OPS            FALSE      FALSE
1 subsets of each size up to 14
Selection Algorithm: forward
          G   AB  R   H   X2B X3B HR  RBI SB  CS  BB  SO  IBB HBP SH  SF  GIDP BA  PA  TB 
1  ( 1 )  " " " " " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
2  ( 1 )  " " " " " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
3  ( 1 )  "*" " " " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
4  ( 1 )  "*" "*" " " " " " " " " " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
5  ( 1 )  "*" "*" " " " " " " "*" " " "*" " " " " " " " " " " " " " " " " " "  " " " " " "
6  ( 1 )  "*" "*" " " " " " " "*" " " "*" " " " " " " " " " " " " "*" " " " "  " " " " " "
7  ( 1 )  "*" "*" " " " " "*" "*" " " "*" " " " " " " " " " " " " "*" " " " "  " " " " " "
8  ( 1 )  "*" "*" " " " " "*" "*" " " "*" " " " " " " " " " " " " "*" " " "*"  " " " " " "
9  ( 1 )  "*" "*" " " " " "*" "*" " " "*" " " " " " " " " "*" " " "*" " " "*"  " " " " " "
10  ( 1 ) "*" "*" " " " " "*" "*" " " "*" " " " " " " " " "*" " " "*" " " "*"  " " " " " "
11  ( 1 ) "*" "*" "*" " " "*" "*" " " "*" " " " " " " " " "*" " " "*" " " "*"  " " " " " "
12  ( 1 ) "*" "*" "*" " " "*" "*" " " "*" " " "*" " " " " "*" " " "*" " " "*"  " " " " " "
13  ( 1 ) "*" "*" "*" " " "*" "*" " " "*" "*" "*" " " " " "*" " " "*" " " "*"  " " " " " "
14  ( 1 ) "*" "*" "*" " " "*" "*" " " "*" "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
          SlugPct OBP OPS BABIP K_Percent BB_Percent
1  ( 1 )  " "     " " " " " "   " "       " "       
2  ( 1 )  " "     " " " " " "   " "       "*"       
3  ( 1 )  " "     " " " " " "   " "       "*"       
4  ( 1 )  " "     " " " " " "   " "       "*"       
5  ( 1 )  " "     " " " " " "   " "       "*"       
6  ( 1 )  " "     " " " " " "   " "       "*"       
7  ( 1 )  " "     " " " " " "   " "       "*"       
8  ( 1 )  " "     " " " " " "   " "       "*"       
9  ( 1 )  " "     " " " " " "   " "       "*"       
10  ( 1 ) " "     " " " " " "   "*"       "*"       
11  ( 1 ) " "     " " " " " "   "*"       "*"       
12  ( 1 ) " "     " " " " " "   "*"       "*"       
13  ( 1 ) " "     " " " " " "   "*"       "*"       
14  ( 1 ) " "     " " " " " "   "*"       "*"       
======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
reg.summary <- summary(regfit.fwd) #get the summary

par(mfrow=c(2,2))
#rss plot -  NOT USEFUL
plot(reg.summary$rss ,xlab="Number of Variables ",ylab="RSS",type="l")

#adjr2 plot
plot(reg.summary$adjr2 ,xlab="Number of Variables ", ylab="Adjusted RSq",type="l")

max_adjr2 <- which.max(reg.summary$adjr2)
points(max_adjr2,reg.summary$adjr2[max_adjr2], col="red",cex=2,pch=20)

# AIC criterion (Cp) to minimize
plot(reg.summary$cp ,xlab="Number of Variables ",ylab="Cp", type='l')

min_cp <- which.min(reg.summary$cp )
points(min_cp, reg.summary$cp[min_cp],col="red",cex=2,pch=20)

# BIC criterion to minimize
plot(reg.summary$bic ,xlab="Number of Variables ",ylab="BIC",type='l')

min_bic <- which.min(reg.summary$bic)
points(min_bic,reg.summary$bic[min_bic],col="red",cex=2,pch=20)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
#Backwards stepwise selection
regfit.bwd = regsubsets(salary ~. , data=bstats_salary_numvars,nvmax=13, method ="backward")
3  linear dependencies found
Reordering variables and trying again:
summary(regfit.bwd)
Subset selection object
Call: regsubsets.formula(salary ~ ., data = bstats_salary_numvars, 
    nvmax = 13, method = "backward")
26 Variables  (and intercept)
           Forced in Forced out
G              FALSE      FALSE
AB             FALSE      FALSE
R              FALSE      FALSE
H              FALSE      FALSE
X2B            FALSE      FALSE
X3B            FALSE      FALSE
HR             FALSE      FALSE
RBI            FALSE      FALSE
SB             FALSE      FALSE
CS             FALSE      FALSE
BB             FALSE      FALSE
SO             FALSE      FALSE
IBB            FALSE      FALSE
HBP            FALSE      FALSE
SH             FALSE      FALSE
SF             FALSE      FALSE
GIDP           FALSE      FALSE
BA             FALSE      FALSE
SlugPct        FALSE      FALSE
OBP            FALSE      FALSE
BABIP          FALSE      FALSE
K_Percent      FALSE      FALSE
BB_Percent     FALSE      FALSE
PA             FALSE      FALSE
TB             FALSE      FALSE
OPS            FALSE      FALSE
1 subsets of each size up to 14
Selection Algorithm: backward
          G   AB  R   H   X2B X3B HR  RBI SB  CS  BB  SO  IBB HBP SH  SF  GIDP BA  PA  TB 
1  ( 1 )  " " " " " " " " " " " " " " " " " " " " "*" " " " " " " " " " " " "  " " " " " "
2  ( 1 )  " " "*" " " " " " " " " " " " " " " " " "*" " " " " " " " " " " " "  " " " " " "
3  ( 1 )  "*" "*" " " " " " " " " " " " " " " " " "*" " " " " " " " " " " " "  " " " " " "
4  ( 1 )  "*" "*" " " " " " " " " " " " " " " " " "*" " " " " " " "*" " " " "  " " " " " "
5  ( 1 )  "*" "*" " " " " " " "*" " " " " " " " " "*" " " " " " " "*" " " " "  " " " " " "
6  ( 1 )  "*" "*" " " " " " " "*" " " " " " " " " "*" " " "*" " " "*" " " " "  " " " " " "
7  ( 1 )  "*" "*" " " " " " " "*" " " " " " " " " "*" " " "*" " " "*" " " "*"  " " " " " "
8  ( 1 )  "*" "*" " " " " "*" "*" " " " " " " " " "*" " " "*" " " "*" " " "*"  " " " " " "
9  ( 1 )  "*" "*" " " " " "*" "*" " " " " " " " " "*" " " "*" " " "*" " " "*"  " " " " " "
10  ( 1 ) "*" "*" " " " " "*" "*" " " " " " " "*" "*" " " "*" " " "*" " " "*"  " " " " " "
11  ( 1 ) "*" "*" " " " " "*" "*" " " " " "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
12  ( 1 ) "*" "*" " " " " "*" "*" " " "*" "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
13  ( 1 ) "*" "*" " " " " "*" "*" "*" "*" "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
14  ( 1 ) "*" "*" " " " " "*" "*" "*" "*" "*" "*" "*" " " "*" " " "*" " " "*"  " " " " " "
          SlugPct OBP OPS BABIP K_Percent BB_Percent
1  ( 1 )  " "     " " " " " "   " "       " "       
2  ( 1 )  " "     " " " " " "   " "       " "       
3  ( 1 )  " "     " " " " " "   " "       " "       
4  ( 1 )  " "     " " " " " "   " "       " "       
5  ( 1 )  " "     " " " " " "   " "       " "       
6  ( 1 )  " "     " " " " " "   " "       " "       
7  ( 1 )  " "     " " " " " "   " "       " "       
8  ( 1 )  " "     " " " " " "   " "       " "       
9  ( 1 )  "*"     " " " " " "   " "       " "       
10  ( 1 ) "*"     " " " " " "   " "       " "       
11  ( 1 ) "*"     " " " " " "   " "       " "       
12  ( 1 ) "*"     " " " " " "   " "       " "       
13  ( 1 ) "*"     " " " " " "   " "       " "       
14  ( 1 ) "*"     " " " " "*"   " "       " "       
======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
reg.summary <- summary(regfit.bwd) #get the summary

par(mfrow=c(2,2))
#rss plot -  NOT USEFUL
plot(reg.summary$rss ,xlab="Number of Variables ",ylab="RSS",type="l")

#adjr2 plot
plot(reg.summary$adjr2 ,xlab="Number of Variables ", ylab="Adjusted RSq",type="l")

max_adjr2 <- which.max(reg.summary$adjr2)
points(max_adjr2, reg.summary$adjr2[max_adjr2], col="red", cex=2, pch=20)

# AIC criterion (Cp) to minimize
plot(reg.summary$cp ,xlab="Number of Variables ",ylab="Cp", type='l')

min_cp <- which.min(reg.summary$cp )
points(min_cp, reg.summary$cp[min_cp], col="red", cex=2, pch=20)

# BIC criterion to minimize
plot(reg.summary$bic, xlab="Number of Variables ", ylab="BIC", type='l')

min_bic <- which.min(reg.summary$bic)
points(min_bic, reg.summary$bic[min_bic], col="red", cex=2, pch=20)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
plot(cv_ridge)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
lbs_fun <- function(fit, offset_x=1, ...) {
  L <- length(fit$lambda)
  x <- log(fit$lambda[L]) + offset_x
  y <- fit$beta[ ,L]
  labs <- names(y)
  text(x, y, labels=labs, ...)
}

plot(ridge, xvar = "lambda", label=T)
lbs_fun(ridge) # add namnes

abline(v = log(cv_ridge$lambda.min), col = "red", lty=2) #lambda.min
abline(v = log(cv_ridge$lambda.1se), col="blue", lty=2)  #lambda.1se

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
# Make predictions on the test data
predictions <- min_ridge %>% predict(x_var) %>% as.vector()

# Model performance metrics
data.frame(
  RMSE = RMSE(predictions, y_var),
  Rsquare = R2(predictions, y_var)
)
<<<<<<< HEAD ======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
plot(cv_lasso)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
lbs_fun <- function(fit, offset_x=1, ...) {
  L <- length(fit$lambda)
  x <- log(fit$lambda[L])+ offset_x
  y <- fit$beta[, L]
  labs <- names(y)
  text(x, y, labels=labs, ...)
}
plot(lasso, xvar = "lambda", label=T)
lbs_fun(lasso)

abline(v=log(cv_lasso$lambda.min), col = "red", lty=2)
abline(v=log(cv_lasso$lambda.1se), col="blue", lty=2)

======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 <<<<<<< HEAD
# Make predictions on the test data
predictions <- min_lasso %>% predict(x_var) %>% as.vector()
# Model performance metrics
data.frame(
  RMSE = RMSE(predictions, y_var),
  Rsquare = R2(predictions, y_var)
)
<<<<<<< HEAD ======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf

Salary Data

<<<<<<< HEAD
ggplot(avg_team_salaries, 
       aes(x = yearID, y = salary, group = factor(franchise))) +
       geom_path() +
       labs(x = "Year", y = "Average team salary (millions USD)")
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
ggplot(Salaries, aes(x = factor(yearID), y = salary/1e5)) +
   geom_boxplot(fill = "lightblue", outlier.size = 1) +
   labs(x = "Year", y = "Salary (per $1,000,000)") +
   coord_flip()
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
avg_team_salaries1 <- Salaries %>%
    group_by(yearID, franchise, lgID) %>%
    summarise(salary= mean(salary)/1e6) %>%
    filter(!(franchise == "CLE" & lgID == "NL")) %>%
    filter(yearID >= 2002)
`summarise()` has grouped output by 'yearID', 'franchise'. You can override using the `.groups` argument.
avg_team_salaries1 %>%
  arrange(desc(salary))
<<<<<<< HEAD ======= >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815
======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
ggplot(avg_team_salaries1, aes(x = franchise, y = salary)) +
  geom_bar(stat = "identity") +
  labs(x = "Team", y = "Salary (per $100,000)")
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf <<<<<<< HEAD
ggplot(avg_team_salaries1, aes(x = franchise, y = salary, fill = franchise)) +
   geom_boxplot(outlier.size = 1) +
   labs(x = "Year", y = "Average Team Salary Since 2002 (per $10,000,000)") +
   coord_flip()
<<<<<<< HEAD

=======

>>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815 ======= >>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf
<<<<<<< HEAD
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKYGBge3J9CnJtKGxpc3QgPSBscygpKQoKbGlicmFyeShMYWhtYW4pCmxpYnJhcnkobW9zYWljKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShtcGxvdCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNsdXN0ZXIpCmxpYnJhcnkoZmFjdG9leHRyYSkKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KG1vZCkKbGlicmFyeShtb2RlbHIpCmxpYnJhcnkobGVhcHMpCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkoSVNMUjIpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShnbG1uZXQpCmBgYAoKYGBge3J9CiNMb2FkIGluIFBlb3BsZSwgQmF0dGluZywgYW5kIFBpdGNoaW5nIERhdGFmcmFtZXMKZGF0YSgiUGVvcGxlIikgCmRhdGEoIkJhdHRpbmciKQpkYXRhKCJQaXRjaGluZyIpCmBgYAoKYGBge3J9CiNMb29raW5nIGF0IHZhcnMgaW4gYWxsIGRhdGEgZnJhbWVzIApuYW1lcyhQZW9wbGUpCmBgYAoKYGBge3J9Cm5hbWVzKEJhdHRpbmcpCmBgYAoKYGBge3J9Cm5hbWVzKFBpdGNoaW5nKQpgYGAKCgpgYGB7cn0KI0xvb2tpbmcgYXQgeWVhcnMgClBpdGNoaW5nJT4lCiBhcnJhbmdlKHllYXJJRCkgCmBgYAoKCmBgYHtyfQojTWVyZ2VzIHBsYXllciBuYW1lIHRvIEJhdHRpbmcgZGF0YS4gCmJzdGF0cyA8LSBiYXR0aW5nU3RhdHMoKQoJc3RyKGJzdGF0cykKCQoKUGVvcGxlJG5hbWUgPC0gcGFzdGUoUGVvcGxlJG5hbWVGaXJzdCwgUGVvcGxlJG5hbWVMYXN0LCBzZXAgPSAiICIpCgpiYXR0aW5nX25hbWUgPC0gbWVyZ2UoQmF0dGluZywKICAgICAgICAgICAgICAgICBQZW9wbGVbLGMoInBsYXllcklEIiwgIm5hbWUiKV0sCiAgICAgICAgICAgICAgICAgYnkgPSAicGxheWVySUQiLCBhbGwueCA9IFRSVUUpCgojTWVyZ2VzIHBsYXllciBuYW1lIHRvIFBpdGNoaW5nIGRhdGEuCgpQZW9wbGUkbmFtZSA8LSBwYXN0ZShQZW9wbGUkbmFtZUZpcnN0LCBQZW9wbGUkbmFtZUxhc3QsIHNlcCA9ICIgIikKCnBpdGNoaW5nX25hbWUgPC0gbWVyZ2UoUGl0Y2hpbmcsCiAgICAgICAgICAgICAgICAgUGVvcGxlWyxjKCJwbGF5ZXJJRCIsICJuYW1lIildLAogICAgICAgICAgICAgICAgIGJ5ID0gInBsYXllcklEIiwgYWxsLnggPSBUUlVFKQpgYGAKCmBgYHtyfQojQ3JlYXRpbmcgYWRkaXRpb25hbCBzdGF0cyBmb3IgYnN0YXRzCmJzdGF0c1tpcy5uYShic3RhdHMpXSA9IDAKI2lzLm5hbihic3RhdHMpCgpic3RhdHMgPC0gYnN0YXRzICU+JQogIG11dGF0ZShLX1BlcmNlbnQgPSBTTyAvIFBBKSAlPiUKICBtdXRhdGUoQkJfUGVyY2VudCA9IChCQiArIElCQikgLyBQQSkgJT4lCiAgbXV0YXRlX2FsbCh+cmVwbGFjZSguLCBpcy5uYW4oLiksIDApKQoKYGBgCgpgYGB7cn0KYnN0YXRzIDwtIGJzdGF0cyAlPiUKICBtdXRhdGVfYXQodmFycyhLX1BlcmNlbnQsIEJCX1BlcmNlbnQpLCBmdW5zKHJvdW5kKC4sIDMpKSkKYGBgCgpgYGB7cn0KYnN0YXRzX3NhbGFyeSA8LSBic3RhdHMgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKHllYXJJRCA+PSAxOTg1KSAlPiUKICAgICAgICAgICAgICBsZWZ0X2pvaW4oc2VsZWN0KFNhbGFyaWVzLCBwbGF5ZXJJRCwgeWVhcklELCB0ZWFtSUQsIHNhbGFyeSksIAogICAgICAgICAgICAgICAgICAgICAgICAgYnk9YygicGxheWVySUQiLCAieWVhcklEIiwgInRlYW1JRCIpKQoKYnN0YXRzX3NhbGFyeVtpcy5uYShic3RhdHNfc2FsYXJ5KV0gPSAwCnN0cihic3RhdHNfc2FsYXJ5KQoKYGBgCgpgYGB7cn0KYnN0YXRzX3N1cmUgPC0gYnN0YXRzX3NhbGFyeSAlPiUKICBmaWx0ZXIoUEEgPiAxNTApICU+JQogIHNlbGVjdChPUFMsIEJBQklQLCBLX1BlcmNlbnQsIEJCX1BlcmNlbnQsIHNhbGFyeSkKYGBgCgojIyBEYXRhIFByZXBhcmF0aW9uIChMZXNzb24gMSAmIDIpCgpgYGB7cn0KI0tlZXAgcGxheWVycyB3aXRoIG92ZXIgMTUwIGF0IGJhdHMuIChXZSBjYW4gY2hhbmdlIHRoaXMgdmFsdWUgaWYgbmVjZXNzYXJ5KS4KI0NyZWF0aW5nIGJhdHRpbmcgYXZlcmFnZSB2YXJpYWJsZS4KCmJhdHRpbmcxIDwtIGJzdGF0cyAlPiUKICBmaWx0ZXIoQUIgPj0gMTUwKQogIApgYGAKCmBgYHtyfQpic3RhdHMgJT4lCiAgZmlsdGVyKHBsYXllcklEID09ICJib2dhZXhhMDEiKQpgYGAKCiMjIEV4cGxvcmF0b3J5IEFuYWx5c2lzIChMZXNzb24gMSAmIDIpCkxlc3NvbnMgMSBhbmQgMiB3aWxsIGp1c3QgYmUgcGFydHMgb2YgdGhlIG92ZXJhbGwgcHJvamVjdC4gU2ltcGxlIHRoaW5ncyBsaWtlIGRhdGEgbWFuaXB1bGF0aW9uLCBhcHBseSBmdW5jdGlvbnMsIGJveHBsb3RzLCBldGMuIFRoaXMgd2lsbCBiZSBkYXRhIHByZXBhcmF0aW9uIGl0ZW1zIGFuZCBleHBsb3JhdG9yeSBhbmFseXNpcy4KCmBgYHtyfQpiIDwtIGdncGxvdChiYXR0aW5nMSwgYWVzKHggPSB0ZWFtSUQsIHkgPSBIUikpICsKICBnZW9tX2JveHBsb3QoY29sID0gImJsYWNrIiwgYWVzKGZpbGwgPSB0ZWFtSUQpKQpiCgpgYGAKCmBgYHtyfQpoaXR0ZXJzMSA8LSBiYXR0aW5nMSAlPiUKICBmaWx0ZXIoeWVhcklEIDwgMTg5NSkgJT4lCiAgc2VsZWN0KFNsdWdQY3QpCgpoaXR0ZXJzMiA8LSBiYXR0aW5nMSAlPiUKICBmaWx0ZXIoeWVhcklEID4gMTg5NCwgeWVhcklEIDwgMTkyMSkgJT4lCiAgc2VsZWN0KFNsdWdQY3QpCgpoaXR0ZXJzMyA8LSBiYXR0aW5nMSAlPiUKICBmaWx0ZXIoeWVhcklEID4gMTkyMCwgeWVhcklEIDwgMTk2OSkgJT4lCiAgc2VsZWN0KFNsdWdQY3QpCgpoaXR0ZXJzNCA8LSBiYXR0aW5nMSAlPiUKICBmaWx0ZXIoeWVhcklEID4gMTk2OSkgJT4lCiAgc2VsZWN0KFNsdWdQY3QpCiNPcmdhbml6aW5nIDQgZGlmZmVyZW50IGRhdGFzZXRzIGxvb2tpbmcgYXQgc2x1Z2dpbmcgcGVyY2VudGFnZSBmb3IgdGhlIGZvbGxvd2luZyBib3hwbG90cy4gQWxsIG9mIHRoZXNlIGFyZSBzb21ld2hhdCBkaWZmZXJlbnQgZXJhcywgd2l0aCB0aGUgbW9zdCBkcmFtYXRpYyBzcGxpdCBiZWluZyBmcm9tIGJlZm9yZSAxOTIwIChwcmUtQmFiZSBSdXRoKSBhbmQgYWZ0ZXIgMTkyMCAoZHVyaW5nIGFuZCBwb3N0LUJhYmUgUnV0aCkKYGBgCgpgYGB7cn0KYm94cGxvdChoaXR0ZXJzMSwKICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSBsYXRlIDE4NzEgLSAxODk0IiwKICAgICAgICB5bGFiID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UiLAogICAgICAgIGNvbCA9ICJibHVlIiwKICAgICAgICBob3Jpem9udGFsID0gVFJVRSkKYGBgCgpgYGB7cn0KYm94cGxvdChoaXR0ZXJzMiwgCiAgICAgICAgbWFpbiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIGZyb20gMTg5NS0xOTIwIiwKICAgICAgICB5bGFiID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UiLAogICAgICAgIGNvbCA9ICJ5ZWxsb3ciLAogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQpgYGAKCmBgYHtyfQpib3hwbG90KGhpdHRlcnMzLCAKICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSAxOTIxLTE5NjgiLAogICAgICAgIHlsYWIgPSAiU2x1Z2dpbmcgcGVyY2VudGFnZSIsCiAgICAgICAgY29sID0gInJlZCIsCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUpCmBgYAoKYGBge3J9CmJveHBsb3QoaGl0dGVyczQsIAogICAgICAgIG1haW4gPSAiU2x1Z2dpbmcgcGVyY2VudGFnZSBmcm9tIDE5NjkgLSBwcmVzZW50IiwKICAgICAgICB5bGFiID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UiLAogICAgICAgIGNvbCA9ICJyZWQiLAogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQpgYGAKCgpgYGB7cn0Kc2FwcGx5KGhpdHRlcnMxLCBtZWFuLCBuYS5ybSA9IFQpCnNhcHBseShoaXR0ZXJzMiwgbWVhbiwgbmEucm0gPSBUKQpzYXBwbHkoaGl0dGVyczMsIG1lYW4sIG5hLnJtID0gVCkKc2FwcGx5KGhpdHRlcnM0LCBtZWFuLCBuYS5ybSA9IFQpCiNOb3RpY2UgdGhhdCBnaWdhbnRpYyBpbmNyZWFzZSBiZXR3ZWVuIGhpdHRlcnMyIGFuZCBoaXR0ZXJzMwpgYGAKCmBgYHtyfQpzdW1tYXJ5KGhpdHRlcnMxKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGhpdHRlcnMyKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGhpdHRlcnMzKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGhpdHRlcnM0KQpgYGAKCmBgYHtyfQojS2VlcCBiYXR0aW5nIHN0YXRzIHRoYXQgd2Ugd2FudCBmb3IgcGFpcnMuCmJhdHRpbmdfbnVtIDwtIGJzdGF0cyAlPiUKICBmaWx0ZXIoUEEgPj0gMTUwKSAlPiUKICBzZWxlY3QoIkJBIiwgJ09CUCcsICdTbHVnUGN0JywgIlNPIiwgIkJCIiwgIkhSIikKICAKYGBgCgpgYGB7cn0KcGFpcnMoYmF0dGluZ19udW0pCmBgYAojIyMjIENhcmVlciBCYXR0aW5nIFN0YXRzCmBgYHtyfQpjYXJlZXJCYXR0aW5nIDwtIG5hLm9taXQoYnN0YXRzKQpgYGAKCmBgYHtyfQpjYXJlZXJCYXR0aW5nIDwtIGNhcmVlckJhdHRpbmcgJT4lCiAgc2VsZWN0KHBsYXllcklELCBCQSwgUEEsIFNsdWdQY3QsIE9CUCwgU08sIEhSKSAlPiUKICBncm91cF9ieShwbGF5ZXJJRCkgJT4lCiAgc3VtbWFyaXNlX2FsbCgnbWVhbicpCmBgYAoKYGBge3J9CmNhcmVlckJhdHRpbmdfbnVtIDwtIGNhcmVlckJhdHRpbmcgJT4lCiAgZmlsdGVyKFBBID49IDE1MCkgJT4lCiAgc2VsZWN0KEJBLCBQQSwgU2x1Z1BjdCwgT0JQLCBTTywgSFIpCgpwYWlycyhjYXJlZXJCYXR0aW5nX251bSkKYGBgCmBgYHtyfQpjb3JybWF0cml4IDwtIGNvcihiYXR0aW5nX251bSkKY29ycnBsb3QoY29ycm1hdHJpeCwgbWV0aG9kID0gJ251bWJlcicpICNHaXZlcyB1cyBjb3JyZWxhdGlvbiBmcm9tIHBhaXJzIGdyYXBoLgpgYGAKCmBgYHtyfQpjYXJlZXJCYXR0aW5nX251bTEgPC0gY2FyZWVyQmF0dGluZ19udW0gJT4lCiAgZmlsdGVyKFBBID4gNTAwKQpgYGAKCgojIyAwLWRpbWVuc2lvbmFsIFJlZHVjdGlvbiAoTGVzc29uIDQpCgoKIyMjIyBCb290c3RyYXBwaW5nCgojIyBQQ0EgKExlc3NvbiA0KQpgYGB7cn0KcmVzIDwtIGJhdHRpbmdfbnVtICU+JSBwcmNvbXAoc2NhbGUgPSBUUlVFKQpyZXMKYGBgCgpgYGB7cn0KbG9hZGluZ3MgPC0gcmVzJHJvdGF0aW9uCmxvYWRpbmdzCmBgYAoKYGBge3J9CnNjb3JlX21hdCA8LSByZXMkeApzY29yZV9tYXQKYGBgCgoKYGBge3J9CmdldF9laWcocmVzKQpgYGAKCiMjIyMgU2NyZWVwbG90CmBgYHtyfQpnZXRfZWlnKHJlcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gMTo2LCB5ID0gY3VtdWxhdGl2ZS52YXJpYW5jZS5wZXJjZW50KSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDgwKSArCiAgeGxhYigiUHJpbmNpcGFsIENvbXBvbmVudCIpICsKICB5bGFiKCJQcm9wb3J0aW9uIG9mIFZhcmlhbmNlIEV4cGxhaW5lZCIpICsKICBnZ3RpdGxlKCJTY3JlZSBQbG90IG9mIFByaW5jaXBhbCBDb21wb25lbnQgZm9yIEJhdHRpbmcgU3RhdGlzdGljcyIpCmBgYAoKMiBQcmluY2lwYWwgQ29tcG9uZW50czogUEMxIGFuZCBQQzIKCmBgYHtyfQpmdml6X3NjcmVlcGxvdChyZXMsIG1haW4gPSAiU2NyZWUgUGxvdCIpCmBgYAoKQ2FuIElkZW50aWZ5IGFuIGVsYm93IGluIDMuCgojIyMjIEJpcGxvdApgYGB7cn0KcmVzICU+JQogIGZ2aXpfcGNhX3ZhcihheGVzID0gYygxLDIpLAogICAgICAgICAgICAgICBjb2wudmFyID0gImNvbnRyaWIiLAogICAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwKICAgICAgICAgICAgICAgcmVwZWwgPSBUUlVFCiAgICAgICAgICAgICAgICkKYGBgCgoKIyMgQ2x1c3RlciBBbmFseXNpcyAoTGVzc29uIDUpCmBgYHtyfQojTk9UIENPTVBMRVRFISEhISEgVGhpcyB3YXMganVzdCBhIHRlc3QsIGJzdGF0cyBpcyB3YXkgdG9vIGJpZy4KYnN0YXRzX2Jlc3QgPC0gYnN0YXRzICU+JQogIGZpbHRlcihQQSA+PSA2MDApCgpldV9kaXN0IDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gJ2V1Y2xpZGVhbicpCmBgYAoKYGBge3J9CmhjX2NvbXBsZXRlIDwtIGhjbHVzdChldV9kaXN0LCBtZXRob2QgPSAnY29tcGxldGUnKQoKcGxvdChoY19jb21wbGV0ZSkKYGBgCgojIyMjIFNpbGhvdWV0dGUKCmBgYHtyfQpyZXNfdGVzdCA8LSBjYXJlZXJCYXR0aW5nX251bTEgJT4lIGttZWFucyg3KQogIHN0cihyZXNfdGVzdCkKYGBgCgoKYGBge3J9CmRpc3RhbmNlIDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gImV1Y2xpZGVhbiIpCnNpbCA8LSBzaWxob3VldHRlKHggPSByZXNfdGVzdCRjbHVzdGVyLCBkaXN0ID0gZGlzdGFuY2UpCnN1bW1hcnkoc2lsKQpzaWwgJT4lIGhlYWQoKQpgYGAKCmBgYHtyfQpmdml6X3NpbGhvdWV0dGUoc2lsKQpgYGAKCmBgYHtyfQpmdml6X25iY2x1c3QoY2FyZWVyQmF0dGluZ19udW0xLCBoY3V0LCBoY19tZXRob2QgPSAiY29tcGxldGUiLCBoY19tZXRyaWMgPSAiZXVjbGlkZWFuIiwgbWV0aG9kID0gIndzcyIpCmBgYAoKYGBge3J9CiMjVGhpcyBpcyB0byB0ZXN0IG90aGVyIHZhbHVlcyBvZiBLIGZvciB0aGUgc2lsaG91ZXR0ZSBtZXRob2QuCnJlc190ZXN0MSA8LSBjYXJlZXJCYXR0aW5nX251bTEgJT4lIGttZWFucygxMCApCiAgc3RyKHJlc190ZXN0MSkKYGBgCgoKYGBge3J9CmRpc3RhbmNlIDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kPSJldWNsaWRlYW4iKQpzaWwgPC0gc2lsaG91ZXR0ZSh4ID0gcmVzX3Rlc3QxJGNsdXN0ZXIsIGRpc3QgPSBkaXN0YW5jZSkKc3VtbWFyeShzaWwpCnNpbCAlPiUgaGVhZCgpCmBgYAoKYGBge3J9CmZ2aXpfc2lsaG91ZXR0ZShzaWwpCmBgYAoKCiMjIyMgRGlhbmEKCiMjIExpbmVhciBSZWdyZXNzaW9uIChMZXNzb24gNikKCkxpbmVhciBSZWdyZXNzaW9uIGNvbXBhcmluZyB0ZWFtIHBheXJvbGwgYW5kIHdpbiByYXRlLgpgYGB7cn0KdGVhbXMgPSBhcy5kYXRhLnRhYmxlKFRlYW1zKQp0ZWFtcyA9IHRlYW1zWywgLih5ZWFySUQsCiAgICAgICAgICAgICAgICAgIGxnSUQgPSBhcy5jaGFyYWN0ZXIobGdJRCksCiAgICAgICAgICAgICAgICAgIHRlYW1JRCA9IGFzLmNoYXJhY3Rlcih0ZWFtSUQpLAogICAgICAgICAgICAgICAgICBmcmFuY2hJRCA9IGFzLmNoYXJhY3RlcihmcmFuY2hJRCksCiAgICAgICAgICAgICAgICAgIFJhbmssIEcsIFcsIEwsIFIsIEVSQSwgU08sCiAgICAgICAgICAgICAgICAgIFdpblBlcmNlbnQgPSBXLyhXK0wpKV0KCnNhbGFyaWVzID0gYXMuZGF0YS50YWJsZShTYWxhcmllcykKc2FsYXJpZXMgPSBzYWxhcmllc1ssIGMoImxnSUQiLCAidGVhbUlEIiwgInNhbGFyeTFNIikgOj0KICAgICAgICAgICAgICAgICAgICAgIGxpc3QoYXMuY2hhcmFjdGVyKGxnSUQpLCBhcy5jaGFyYWN0ZXIodGVhbUlEKSwgc2FsYXJ5IC8gMWU2TCldCnBheXJvbGwgPSBzYWxhcmllc1ssIC4ocGF5cm9sbCA9IHN1bShzYWxhcnkxTSkpLCBieT0uKHRlYW1JRCwgeWVhcklEKV0KdGVhbVBheXJvbGwgPSBtZXJnZSh0ZWFtcywgcGF5cm9sbCwgYnkgPSBjKCJ0ZWFtSUQiLCAieWVhcklEIikpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gdGVhbVBheXJvbGwsIGFlcyh4ID0gcGF5cm9sbCwgeSA9IFdpblBlcmNlbnQpKSArIGdlb21fcG9pbnQoKSAgKyBsYWJzKHggPSAiUGF5cm9sbCAoaW4gbWlsbGlvbnMpIiwgeSA9ICJXaW4gUGVyY2VudGFnZSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgc2UgPSBGQUxTRSkKCmBgYApgYGB7cn0KbW9kX2xtIDwtIGxtKGRhdGEgPSB0ZWFtUGF5cm9sbCwgV2luUGVyY2VudH5wYXlyb2xsKQptb2RfbG0KYGBgCgpgYGB7cn0Kc3VtbWFyeShtb2RfbG0pCmBgYApgYGB7cn0KcGF5cm9sbF9wcmVkIDwtIHRlYW1QYXlyb2xsICU+JQogIGFkZF9wcmVkaWN0aW9ucyhtb2RfbG0pCgpwYXlyb2xsX3ByZWQgJT4lCiAgZmlsdGVyKHllYXJJRCA+PSAyMDEwKSAlPiUKICBhcnJhbmdlKGRlc2MocHJlZCkpICU+JQogIGhlYWQoMjUpCmBgYApgYGB7cn0KcGF5cm9sbF9wcmVkICU+JQogIGZpbHRlcih5ZWFySUQgPj0gMjAxMCkgJT4lCiAgYXJyYW5nZShkZXNjKFdpblBlcmNlbnQpKSAlPiUKICBoZWFkKDI1KQpgYGAKT25seSBmaXZlIHRlYW1zIGFyZSBpbiB0aGUgdG9wIDI1IG9mIGJvdGggcGF5cm9sbCBhbmQgd2luIHBlcmNlbnRhZ2UgaW4gdGhlIDIwMTBzLiBUaGVzZSB0ZWFtcyBhcmUgdGhlIDIwMTEgUGhpbGxpZXMsIDIwMTEgWWFua2VlcywgMjAxMCBZYW5rZWVzLCAyMDEyIFlhbmtlZXMsIGFuZCAyMDE2IFJhbmdlcnMuIFRoaXMgc2hvd3MgdGhhdCBzcGVuZGluZyB0aGUgbW9zdCBtb25leSBkb2Vzbid0IGF1dG9tYXRpY2FsbHkgbWVhbiB5b3UgYXJlIGdldHRpbmcgdGhlIGJlc3QgcHJvZHVjdCBvbiB0aGUgZmllbGQuCiMjIFNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbgoKIyMgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24KYGBge3J9CmJzdGF0c19zYWxhcnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUKICBmaWx0ZXIoUEEgPj0gMTAwKSAlPiUKICBmaWx0ZXIoc2FsYXJ5ID4gNTAwMDAwKQpgYGAKCgpgYGB7cn0KbG1fbW9kIDwtIGxtKHNhbGFyeSB+IEgsIEhSLCBkYXRhID0gYnN0YXRzX3NhbGFyeSkKc3VtbWFyeShsbV9tb2QpCmBgYAoKYGBge3J9CmxtX21vZF9wcmQgPC0gYnN0YXRzX3NhbGFyeSAlPiUgYWRkX3ByZWRpY3Rpb25zKGxtX21vZCkKbG1fbW9kX3ByZApgYGAKCmBgYHtyfQpmdWxsX21vZGVsIDwtIGxtKHNhbGFyeSB+LiwgZGF0YSA9IGJzdGF0c19zdXJlKQpzdW1tYXJ5KGZ1bGxfbW9kZWwpCmBgYAoKYGBge3J9CmZ1bGxfbW9kZWxfcHJlZCA8LSBic3RhdHNfc3VyZSAlPiUgYWRkX3ByZWRpY3Rpb25zKGZ1bGxfbW9kZWwpCmZ1bGxfbW9kZWxfcHJlZApgYGAKCmBgYHtyfQphZHZfc3RhdF9tb2QgPC0gbG0oc2FsYXJ5IH4gT1BTLCBkYXRhID0gYnN0YXRzX3NhbGFyeSkKc3VtbWFyeShhZHZfc3RhdF9tb2QpCmBgYAoKCiMjIFJlc2FtcGxpbmcgTWV0aG9kcwoKYGBge3J9CiNpbmNsdWRpbmcgMjAwMiBhbmQgdXAgYmVjYXVzZSBzYWxhcnkgYmVjb21lcyBoaWdoZXIKYnN0YXRzX3NhbGFyeV8yMWNlbnR1cnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUKICBmaWx0ZXIoeWVhcklEID49IDIwMDIpCmBgYAoKCmBgYHtyfQpic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgaGVhZCgxMCkKYGBgCgpgYGB7cn0KIyBTYWxhcnkgb2YgaGl0dGVycyB3aXRoIGJlc3QgYmF0dGluZyBhdmcgCnRvcF9iYXR0aW5nQVZHIDwtIGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5JT4lCiAgc2VsZWN0KEJBLCBzYWxhcnkpICU+JQogIGFycmFuZ2UoZGVzYyhCQSkpJT4lCiAgaGVhZCgxNTAwKQoKICBnZ3Bsb3QoZGF0YSA9IHRvcF9iYXR0aW5nQVZHLCBhZXMoeCA9IEJBLCB5PSBzYWxhcnkpKSArCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSkgKwogICAgbGFicyh0aXRsZT0iSG93IEJhdHRpbmcgQVZHIGFmZmVjdHMgU2FsYXJ5IikKYGBgCgoKYGBge3J9CiMgc2V0dGluZyBzZWVkIHRvIGdlbmVyYXRlIGEgcmVwcm9kdWNpYmxlIHJhbmRvbSBzYW1wbGluZwpzZXQuc2VlZCgxMjMpCiAKIyBkZWZpbmluZyB0cmFpbmluZyBjb250cm9sIGFzIGNyb3NzLXZhbGlkYXRpb24gYW5kIHZhbHVlIG9mIEsgZXF1YWwgdG8gMTAKdHJhaW5fY29udHJvbCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyID0gMTApCgojIHRyYWluaW5nIHRoZSBtb2RlbAptb2RlbCA8LSB0cmFpbihzYWxhcnkgfiBPQlAsIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSwKICAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwKICAgICAgICAgICAgICAgdHJDb250cm9sID0gdHJhaW5fY29udHJvbCkKCnByaW50KG1vZGVsKQpgYGAKCgojIyBGZWF0dXJlIFNlbGVjdGlvbgpgYGB7cn0KYnN0YXRzX3NhbGFyeV9udW12YXJzIDwtIGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5ICU+JSAKICBzZWxlY3QoYyg2OjMyKSkKYGBgCgpgYGB7cn0KI0NvcnJlbGF0aW9uIG1hcHBpbmcgCgojbWFraW5nIGNvcnJlbGF0aW9uIGhlYXQgbWFwIApjb3JyX251bWVyaWMgPC0gcm91bmQoY29yKGJzdGF0c19zYWxhcnlfbnVtdmFycyksIDEpCgojcGxvdCB0byB2aXN1YWxpemUgdGhlIGNvcnJlbGF0aW9ucyAKZ2djb3JycGxvdChjb3JyX251bWVyaWMsCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsCiAgICAgICAgICAgbGFiID0gVFJVRSwgCiAgICAgICAgICAgbGFiX3NpemUgPSAyLCAgCiAgICAgICAgICAgY29sb3JzID0gYygidG9tYXRvMiIsICJ3aGl0ZSIsICJzcHJpbmdncmVlbjMiKSwKICAgICAgICAgICB0aXRsZT0iQ29ycmVsb2dyYW0gb2YgYmF0dGluZyBEYXRhIiwgCiAgICAgICAgICAgZ2d0aGVtZT10aGVtZV9idykKYGBgCgpgYGB7cn0KcmVnZml0LmZ1bGwgPSByZWdzdWJzZXRzKHNhbGFyeSB+LiwgZGF0YSA9IGJzdGF0c19zYWxhcnlfbnVtdmFycywgIG52bWF4ID0gMTMsIG1ldGhvZD0iZXhoYXVzdGl2ZSIpCnN1bW1hcnkocmVnZml0LmZ1bGwpCmBgYAoKYGBge3J9CnN1bW1hcnkocmVnZml0LmZ1bGwpJHJzcQpgYGAKCgoKYGBge3J9CnBsb3Qoc3VtbWFyeShyZWdmaXQuZnVsbCkkcnNxKQpgYGAKCmBgYHtyfQpyZWcuc3VtbWFyeSA8LSBzdW1tYXJ5KHJlZ2ZpdC5mdWxsKSAjZ2V0IHRoZSBzdW1tYXJ5CgpwYXIobWZyb3c9YygyLDIpKQojcnNzIHBsb3QgLSAgTk9UIFVTRUZVTApwbG90KHJlZy5zdW1tYXJ5JHJzcyAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IlJTUyIsdHlwZT0ibCIpCgojYWRqcjIgcGxvdApwbG90KHJlZy5zdW1tYXJ5JGFkanIyICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIsIHlsYWI9IkFkanVzdGVkIFJTcSIsdHlwZT0ibCIpCgptYXhfYWRqcjIgPC0gd2hpY2gubWF4KHJlZy5zdW1tYXJ5JGFkanIyKQpwb2ludHMobWF4X2FkanIyLHJlZy5zdW1tYXJ5JGFkanIyW21heF9hZGpyMl0sIGNvbD0icmVkIixjZXg9MixwY2g9MjApCgojIEFJQyBjcml0ZXJpb24gKENwKSB0byBtaW5pbWl6ZQpwbG90KHJlZy5zdW1tYXJ5JGNwICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iQ3AiLCB0eXBlPSdsJykKCm1pbl9jcCA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkY3AgKQpwb2ludHMobWluX2NwLCByZWcuc3VtbWFyeSRjcFttaW5fY3BdLGNvbD0icmVkIixjZXg9MixwY2g9MjApCgojIEJJQyBjcml0ZXJpb24gdG8gbWluaW1pemUKcGxvdChyZWcuc3VtbWFyeSRiaWMgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJCSUMiLHR5cGU9J2wnKQoKbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQpwb2ludHMobWluX2JpYyxyZWcuc3VtbWFyeSRiaWNbbWluX2JpY10sY29sPSJyZWQiLGNleD0yLHBjaD0yMCkKYGBgCgpgYGB7cn0KI0ZvcndhcmQgc3RlcHdpc2Ugc2VsZWN0aW9uCnJlZ2ZpdC5md2QgPSByZWdzdWJzZXRzKHNhbGFyeSB+LiAsIGRhdGE9YnN0YXRzX3NhbGFyeV9udW12YXJzLCBudm1heD0xMywgbWV0aG9kID0iZm9yd2FyZCIpCnN1bW1hcnkocmVnZml0LmZ3ZCkKYGBgCgpgYGB7cn0KcmVnLnN1bW1hcnkgPC0gc3VtbWFyeShyZWdmaXQuZndkKSAjZ2V0IHRoZSBzdW1tYXJ5CgpwYXIobWZyb3c9YygyLDIpKQojcnNzIHBsb3QgLSAgTk9UIFVTRUZVTApwbG90KHJlZy5zdW1tYXJ5JHJzcyAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IlJTUyIsdHlwZT0ibCIpCgojYWRqcjIgcGxvdApwbG90KHJlZy5zdW1tYXJ5JGFkanIyICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIsIHlsYWI9IkFkanVzdGVkIFJTcSIsdHlwZT0ibCIpCgptYXhfYWRqcjIgPC0gd2hpY2gubWF4KHJlZy5zdW1tYXJ5JGFkanIyKQpwb2ludHMobWF4X2FkanIyLHJlZy5zdW1tYXJ5JGFkanIyW21heF9hZGpyMl0sIGNvbD0icmVkIixjZXg9MixwY2g9MjApCgojIEFJQyBjcml0ZXJpb24gKENwKSB0byBtaW5pbWl6ZQpwbG90KHJlZy5zdW1tYXJ5JGNwICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iQ3AiLCB0eXBlPSdsJykKCm1pbl9jcCA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkY3AgKQpwb2ludHMobWluX2NwLCByZWcuc3VtbWFyeSRjcFttaW5fY3BdLGNvbD0icmVkIixjZXg9MixwY2g9MjApCgojIEJJQyBjcml0ZXJpb24gdG8gbWluaW1pemUKcGxvdChyZWcuc3VtbWFyeSRiaWMgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJCSUMiLHR5cGU9J2wnKQoKbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQpwb2ludHMobWluX2JpYyxyZWcuc3VtbWFyeSRiaWNbbWluX2JpY10sY29sPSJyZWQiLGNleD0yLHBjaD0yMCkKYGBgCgpgYGB7cn0KI0JhY2t3YXJkcyBzdGVwd2lzZSBzZWxlY3Rpb24KcmVnZml0LmJ3ZCA9IHJlZ3N1YnNldHMoc2FsYXJ5IH4uICwgZGF0YT1ic3RhdHNfc2FsYXJ5X251bXZhcnMsbnZtYXg9MTMsIG1ldGhvZCA9ImJhY2t3YXJkIikKc3VtbWFyeShyZWdmaXQuYndkKQpgYGAKCmBgYHtyfQpyZWcuc3VtbWFyeSA8LSBzdW1tYXJ5KHJlZ2ZpdC5id2QpICNnZXQgdGhlIHN1bW1hcnkKCnBhcihtZnJvdz1jKDIsMikpCiNyc3MgcGxvdCAtICBOT1QgVVNFRlVMCnBsb3QocmVnLnN1bW1hcnkkcnNzICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iUlNTIix0eXBlPSJsIikKCiNhZGpyMiBwbG90CnBsb3QocmVnLnN1bW1hcnkkYWRqcjIgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIiwgeWxhYj0iQWRqdXN0ZWQgUlNxIix0eXBlPSJsIikKCm1heF9hZGpyMiA8LSB3aGljaC5tYXgocmVnLnN1bW1hcnkkYWRqcjIpCnBvaW50cyhtYXhfYWRqcjIsIHJlZy5zdW1tYXJ5JGFkanIyW21heF9hZGpyMl0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkKCiMgQUlDIGNyaXRlcmlvbiAoQ3ApIHRvIG1pbmltaXplCnBsb3QocmVnLnN1bW1hcnkkY3AgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJDcCIsIHR5cGU9J2wnKQoKbWluX2NwIDwtIHdoaWNoLm1pbihyZWcuc3VtbWFyeSRjcCApCnBvaW50cyhtaW5fY3AsIHJlZy5zdW1tYXJ5JGNwW21pbl9jcF0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkKCiMgQklDIGNyaXRlcmlvbiB0byBtaW5pbWl6ZQpwbG90KHJlZy5zdW1tYXJ5JGJpYywgeGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLCB5bGFiPSJCSUMiLCB0eXBlPSdsJykKCm1pbl9iaWMgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGJpYykKcG9pbnRzKG1pbl9iaWMsIHJlZy5zdW1tYXJ5JGJpY1ttaW5fYmljXSwgY29sPSJyZWQiLCBjZXg9MiwgcGNoPTIwKQpgYGAKCmBgYHtyfQojcmlkZ2UgcmVncmVzc2lvbiAKCiMgZ2V0dGluZyB0aGUgcHJlZGljdG9ycwp4X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnMgJT4lIHNlbGVjdCgtc2FsYXJ5KSAlPiUgYXMubWF0cml4KCkKIyBnZXR0aW5nIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZQp5X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnNbLCJzYWxhcnkiXQpgYGAKCmBgYHtyfQpyaWRnZSA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0wKQpzdW1tYXJ5KHJpZGdlKQpgYGAKCmBgYHtyfQpjdl9yaWRnZSA8LSBjdi5nbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYSA9IDApCmN2X3JpZGdlCmBgYAoKYGBge3J9CnBsb3QoY3ZfcmlkZ2UpCmBgYAoKYGBge3J9CmN2X3JpZGdlJGxhbWJkYS5taW4KYGBgCgpgYGB7cn0KY3ZfcmlkZ2UkbGFtYmRhLjFzZQpgYGAKCmBgYHtyfQpsYnNfZnVuIDwtIGZ1bmN0aW9uKGZpdCwgb2Zmc2V0X3g9MSwgLi4uKSB7CiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkKICB4IDwtIGxvZyhmaXQkbGFtYmRhW0xdKSArIG9mZnNldF94CiAgeSA8LSBmaXQkYmV0YVsgLExdCiAgbGFicyA8LSBuYW1lcyh5KQogIHRleHQoeCwgeSwgbGFiZWxzPWxhYnMsIC4uLikKfQoKcGxvdChyaWRnZSwgeHZhciA9ICJsYW1iZGEiLCBsYWJlbD1UKQpsYnNfZnVuKHJpZGdlKSAjIGFkZCBuYW1uZXMKCmFibGluZSh2ID0gbG9nKGN2X3JpZGdlJGxhbWJkYS5taW4pLCBjb2wgPSAicmVkIiwgbHR5PTIpICNsYW1iZGEubWluCmFibGluZSh2ID0gbG9nKGN2X3JpZGdlJGxhbWJkYS4xc2UpLCBjb2w9ImJsdWUiLCBsdHk9MikgICNsYW1iZGEuMXNlCmBgYAoKYGBge3J9Cm1pbl9yaWRnZSA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0wLCBsYW1iZGEgPSBjdl9yaWRnZSRsYW1iZGEubWluKQpjb2VmKG1pbl9yaWRnZSkKYGBgCgpgYGB7cn0KIyBNYWtlIHByZWRpY3Rpb25zIG9uIHRoZSB0ZXN0IGRhdGEKcHJlZGljdGlvbnMgPC0gbWluX3JpZGdlICU+JSBwcmVkaWN0KHhfdmFyKSAlPiUgYXMudmVjdG9yKCkKCiMgTW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljcwpkYXRhLmZyYW1lKAogIFJNU0UgPSBSTVNFKHByZWRpY3Rpb25zLCB5X3ZhciksCiAgUnNxdWFyZSA9IFIyKHByZWRpY3Rpb25zLCB5X3ZhcikKKQpgYGAKCmBgYHtyfQojIExhc3NvIAoKIyBnZXR0aW5nIHRoZSBwcmVkaWN0b3JzCnhfdmFyIDwtIGJzdGF0c19zYWxhcnlfbnVtdmFycyAlPiUgc2VsZWN0KC1zYWxhcnkpICU+JSBhcy5tYXRyaXgoKQojIGdldHRpbmcgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlCnlfdmFyIDwtIGJzdGF0c19zYWxhcnlfbnVtdmFyc1ssInNhbGFyeSJdCmBgYAoKCmBgYHtyfQpsYXNzbyA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0xKQpzdW1tYXJ5KGxhc3NvKQpgYGAKCmBgYHtyfQpjdl9sYXNzbyA8LSBjdi5nbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYSA9IDEpCmN2X2xhc3NvCmBgYAoKYGBge3J9CnBsb3QoY3ZfbGFzc28pCmBgYAoKCmBgYHtyfQpsYnNfZnVuIDwtIGZ1bmN0aW9uKGZpdCwgb2Zmc2V0X3g9MSwgLi4uKSB7CiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkKICB4IDwtIGxvZyhmaXQkbGFtYmRhW0xdKSsgb2Zmc2V0X3gKICB5IDwtIGZpdCRiZXRhWywgTF0KICBsYWJzIDwtIG5hbWVzKHkpCiAgdGV4dCh4LCB5LCBsYWJlbHM9bGFicywgLi4uKQp9CnBsb3QobGFzc28sIHh2YXIgPSAibGFtYmRhIiwgbGFiZWw9VCkKbGJzX2Z1bihsYXNzbykKCmFibGluZSh2PWxvZyhjdl9sYXNzbyRsYW1iZGEubWluKSwgY29sID0gInJlZCIsIGx0eT0yKQphYmxpbmUodj1sb2coY3ZfbGFzc28kbGFtYmRhLjFzZSksIGNvbD0iYmx1ZSIsIGx0eT0yKQpgYGAKCmBgYHtyfQptaW5fbGFzc28gPC0gZ2xtbmV0KHhfdmFyLCB5X3ZhciwgYWxwaGE9MSwgbGFtYmRhID0gY3ZfbGFzc28kbGFtYmRhLm1pbikKY29lZihtaW5fbGFzc28pCmBgYAoKYGBge3J9CnNlX2xhc3NvIDwtIGdsbW5ldCh4X3ZhciwgeV92YXIsIGFscGhhPTEsIGxhbWJkYSA9IGN2X2xhc3NvJGxhbWJkYS4xc2UpCmNvZWYoc2VfbGFzc28pCmBgYAoKYGBge3J9CiMgTWFrZSBwcmVkaWN0aW9ucyBvbiB0aGUgdGVzdCBkYXRhCnByZWRpY3Rpb25zIDwtIG1pbl9sYXNzbyAlPiUgcHJlZGljdCh4X3ZhcikgJT4lIGFzLnZlY3RvcigpCiMgTW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljcwpkYXRhLmZyYW1lKAogIFJNU0UgPSBSTVNFKHByZWRpY3Rpb25zLCB5X3ZhciksCiAgUnNxdWFyZSA9IFIyKHByZWRpY3Rpb25zLCB5X3ZhcikKKQpgYGAKCgoKIyMgU2FsYXJ5IERhdGEKYGBge3J9CmZyYW5jaGlzZSA8LSBjKGBBTkFgID0gIkxBQSIsIGBBUklgID0gIkFSSSIsIGBBVExgID0gIkFUTCIsIAogICAgICAgICAgICAgICBgQkFMYCA9ICJCQUwiLCBgQk9TYCA9ICJCT1MiLCBgQ0FMYCA9ICJMQUEiLAogICAgICAgICAgICAgICBgQ0hBYCA9ICJDSEEiLCBgQ0hOYCA9ICJDSE4iLCBgQ0lOYCA9ICJDSU4iLCAKICAgICAgICAgICAgICAgYENMRWAgPSAiQ0xFIiwgYENPTGAgPSAiQ09MIiwgYERFVGAgPSAiREVUIiwgCiAgICAgICAgICAgICAgIGBGTE9gID0gIk1JQSIsIGBIT1VgID0gIkhPVSIsIGBLQ0FgID0gIktDQSIsIAogICAgICAgICAgICAgICBgTEFBYCA9ICJMQUEiLCBgTEFOYCA9ICJMQU4iLCBgTUlBYCA9ICJNSUEiLCAKICAgICAgICAgICAgICAgYE1JTGAgPSAiTUlMIiwgYE1JTmAgPSAiTUlOIiwgYE1MNGAgPSAiTUlMIiwgCiAgICAgICAgICAgICAgIGBNT05gID0gIldBUyIsIGBOWUFgID0gIk5ZQSIsIGBOWU1gID0gIk5ZTiIsIAogICAgICAgICAgICAgICBgTllOYCA9ICJOWU4iLCBgT0FLYCA9ICJPQUsiLCBgUEhJYCA9ICJQSEkiLCAKICAgICAgICAgICAgICAgYFBJVGAgPSAiUElUIiwgYFNETmAgPSAiU0ROIiwgYFNFQWAgPSAiU0VBIiwKICAgICAgICAgICAgICAgYFNGR2AgPSAiU0ZOIiwgYFNGTmAgPSAiU0ZOIiwgYFNMTmAgPSAiU0xOIiwgCiAgICAgICAgICAgICAgIGBUQkFgID0gIlRCQSIsIGBURVhgID0gIlRFWCIsIGBUT1JgID0gIlRPUiIsCiAgICAgICAgICAgICAgIGBXQVNgID0gIldBUyIpCmBgYAoKYGBge3J9ClNhbGFyaWVzJGZyYW5jaGlzZSA8LSB1bm5hbWUoZnJhbmNoaXNlW1NhbGFyaWVzJHRlYW1JRF0pCmBgYAoKCmBgYHtyfQphdmdfdGVhbV9zYWxhcmllcyA8LSBTYWxhcmllcyAlPiUKICAgIGdyb3VwX2J5KHllYXJJRCwgZnJhbmNoaXNlLCBsZ0lEKSAlPiUKICAgIHN1bW1hcmlzZShzYWxhcnkgPSBtZWFuKHNhbGFyeSkvMWU2KSAlPiUKICAgIGZpbHRlcighKGZyYW5jaGlzZSA9PSAiQ0xFIiAmIGxnSUQgPT0gIk5MIikpCmBgYAoKYGBge3J9CmdncGxvdChhdmdfdGVhbV9zYWxhcmllcywgCiAgICAgICBhZXMoeCA9IHllYXJJRCwgeSA9IHNhbGFyeSwgZ3JvdXAgPSBmYWN0b3IoZnJhbmNoaXNlKSkpICsKICAgICAgIGdlb21fcGF0aCgpICsKICAgICAgIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJBdmVyYWdlIHRlYW0gc2FsYXJ5IChtaWxsaW9ucyBVU0QpIikKYGBgCgpgYGB7cn0KZ2dwbG90KFNhbGFyaWVzLCBhZXMoeCA9IGZhY3Rvcih5ZWFySUQpLCB5ID0gc2FsYXJ5LzFlNSkpICsKICAgZ2VvbV9ib3hwbG90KGZpbGwgPSAibGlnaHRibHVlIiwgb3V0bGllci5zaXplID0gMSkgKwogICBsYWJzKHggPSAiWWVhciIsIHkgPSAiU2FsYXJ5IChwZXIgJDEsMDAwLDAwMCkiKSArCiAgIGNvb3JkX2ZsaXAoKQpgYGAKYGBge3J9CmF2Z190ZWFtX3NhbGFyaWVzMSA8LSBTYWxhcmllcyAlPiUKICAgIGdyb3VwX2J5KHllYXJJRCwgZnJhbmNoaXNlLCBsZ0lEKSAlPiUKICAgIHN1bW1hcmlzZShzYWxhcnk9IG1lYW4oc2FsYXJ5KS8xZTYpICU+JQogICAgZmlsdGVyKCEoZnJhbmNoaXNlID09ICJDTEUiICYgbGdJRCA9PSAiTkwiKSkgJT4lCiAgICBmaWx0ZXIoeWVhcklEID49IDIwMDIpCgphdmdfdGVhbV9zYWxhcmllczEgJT4lCiAgYXJyYW5nZShkZXNjKHNhbGFyeSkpCmBgYApgYGB7cn0KZ2dwbG90KGF2Z190ZWFtX3NhbGFyaWVzMSwgYWVzKHggPSBmcmFuY2hpc2UsIHkgPSBzYWxhcnkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHggPSAiVGVhbSIsIHkgPSAiU2FsYXJ5IChwZXIgJDEwMCwwMDApIikKYGBgCgpgYGB7cn0KZ2dwbG90KGF2Z190ZWFtX3NhbGFyaWVzMSwgYWVzKHggPSBmcmFuY2hpc2UsIHkgPSBzYWxhcnksIGZpbGwgPSBmcmFuY2hpc2UpKSArCiAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAxKSArCiAgIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJBdmVyYWdlIFRlYW0gU2FsYXJ5IFNpbmNlIDIwMDIgKHBlciAkMTAsMDAwLDAwMCkiKSArCiAgIGNvb3JkX2ZsaXAoKQpgYGAKCg==
======= <<<<<<< HEAD
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKCkpDQoNCmxpYnJhcnkoTGFobWFuKQ0KbGlicmFyeShtb3NhaWMpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtcGxvdCkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoY2x1c3RlcikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KG1vZCkNCmxpYnJhcnkobW9kZWxyKQ0KbGlicmFyeShsZWFwcykNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KElTTFIyKQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KbGlicmFyeShnbG1uZXQpDQpgYGANCg0KYGBge3J9DQojTG9hZCBpbiBQZW9wbGUsIEJhdHRpbmcsIGFuZCBQaXRjaGluZyBEYXRhZnJhbWVzDQpkYXRhKCJQZW9wbGUiKSANCmRhdGEoIkJhdHRpbmciKQ0KZGF0YSgiUGl0Y2hpbmciKQ0KYGBgDQoNCmBgYHtyfQ0KI01lcmdlcyBwbGF5ZXIgbmFtZSB0byBCYXR0aW5nIGRhdGEuIA0KYnN0YXRzIDwtIGJhdHRpbmdTdGF0cygpDQoJc3RyKGJzdGF0cykNCgkNCg0KUGVvcGxlJG5hbWUgPC0gcGFzdGUoUGVvcGxlJG5hbWVGaXJzdCwgUGVvcGxlJG5hbWVMYXN0LCBzZXAgPSAiICIpDQoNCmJhdHRpbmdfbmFtZSA8LSBtZXJnZShCYXR0aW5nLA0KICAgICAgICAgICAgICAgICBQZW9wbGVbLGMoInBsYXllcklEIiwgIm5hbWUiKV0sDQogICAgICAgICAgICAgICAgIGJ5ID0gInBsYXllcklEIiwgYWxsLnggPSBUUlVFKQ0KDQojTWVyZ2VzIHBsYXllciBuYW1lIHRvIFBpdGNoaW5nIGRhdGEuDQoNClBlb3BsZSRuYW1lIDwtIHBhc3RlKFBlb3BsZSRuYW1lRmlyc3QsIFBlb3BsZSRuYW1lTGFzdCwgc2VwID0gIiAiKQ0KDQpwaXRjaGluZ19uYW1lIDwtIG1lcmdlKFBpdGNoaW5nLA0KICAgICAgICAgICAgICAgICBQZW9wbGVbLGMoInBsYXllcklEIiwgIm5hbWUiKV0sDQogICAgICAgICAgICAgICAgIGJ5ID0gInBsYXllcklEIiwgYWxsLnggPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KI0NyZWF0aW5nIGFkZGl0aW9uYWwgc3RhdHMgZm9yIGJzdGF0cw0KYnN0YXRzW2lzLm5hKGJzdGF0cyldID0gMA0KI2lzLm5hbihic3RhdHMpDQoNCmJzdGF0cyA8LSBic3RhdHMgJT4lDQogIG11dGF0ZShLX1BlcmNlbnQgPSBTTyAvIFBBKSAlPiUNCiAgbXV0YXRlKEJCX1BlcmNlbnQgPSAoQkIgKyBJQkIpIC8gUEEpICU+JQ0KICBtdXRhdGVfYWxsKH5yZXBsYWNlKC4sIGlzLm5hbiguKSwgMCkpDQoNCmBgYA0KDQpgYGB7cn0NCmJzdGF0cyA8LSBic3RhdHMgJT4lDQogIG11dGF0ZV9hdCh2YXJzKEtfUGVyY2VudCwgQkJfUGVyY2VudCksIGZ1bnMocm91bmQoLiwgMykpKQ0KYGBgDQoNCmBgYHtyfQ0KYnN0YXRzX3NhbGFyeSA8LSBic3RhdHMgJT4lDQogICAgICAgICAgICAgIGZpbHRlcih5ZWFySUQgPj0gMTk4NSkgJT4lDQogICAgICAgICAgICAgIGxlZnRfam9pbihzZWxlY3QoU2FsYXJpZXMsIHBsYXllcklELCB5ZWFySUQsIHRlYW1JRCwgc2FsYXJ5KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgYnk9YygicGxheWVySUQiLCAieWVhcklEIiwgInRlYW1JRCIpKQ0KDQpic3RhdHNfc2FsYXJ5W2lzLm5hKGJzdGF0c19zYWxhcnkpXSA9IDANCnN0cihic3RhdHNfc2FsYXJ5KQ0KDQpgYGANCg0KYGBge3J9DQpic3RhdHNfc3VyZSA8LSBic3RhdHNfc2FsYXJ5ICU+JQ0KICBmaWx0ZXIoUEEgPiAxNTApICU+JQ0KICBzZWxlY3QoT1BTLCBCQUJJUCwgS19QZXJjZW50LCBCQl9QZXJjZW50LCBzYWxhcnkpDQpgYGANCg0KIyMgRGF0YSBQcmVwYXJhdGlvbiAoTGVzc29uIDEgJiAyKQ0KDQpgYGB7cn0NCiNLZWVwIHBsYXllcnMgd2l0aCBvdmVyIDE1MCBhdCBiYXRzLiAoV2UgY2FuIGNoYW5nZSB0aGlzIHZhbHVlIGlmIG5lY2Vzc2FyeSkuDQojQ3JlYXRpbmcgYmF0dGluZyBhdmVyYWdlIHZhcmlhYmxlLg0KDQpiYXR0aW5nMSA8LSBic3RhdHMgJT4lDQogIGZpbHRlcihBQiA+PSAxNTApDQogIA0KYGBgDQoNCmBgYHtyfQ0KYnN0YXRzICU+JQ0KICBmaWx0ZXIocGxheWVySUQgPT0gImJvZ2FleGEwMSIpDQpgYGANCg0KIyMgRXhwbG9yYXRvcnkgQW5hbHlzaXMgKExlc3NvbiAxICYgMikNCkxlc3NvbnMgMSBhbmQgMiB3aWxsIGp1c3QgYmUgcGFydHMgb2YgdGhlIG92ZXJhbGwgcHJvamVjdC4gU2ltcGxlIHRoaW5ncyBsaWtlIGRhdGEgbWFuaXB1bGF0aW9uLCBhcHBseSBmdW5jdGlvbnMsIGJveHBsb3RzLCBldGMuIFRoaXMgd2lsbCBiZSBkYXRhIHByZXBhcmF0aW9uIGl0ZW1zIGFuZCBleHBsb3JhdG9yeSBhbmFseXNpcy4NCg0KYGBge3J9DQpiIDwtIGdncGxvdChiYXR0aW5nMSwgYWVzKHggPSB0ZWFtSUQsIHkgPSBIUikpICsNCiAgZ2VvbV9ib3hwbG90KGNvbCA9ICJibGFjayIsIGFlcyhmaWxsID0gdGVhbUlEKSkNCmINCg0KYGBgDQoNCmBgYHtyfQ0KaGl0dGVyczEgPC0gYmF0dGluZzEgJT4lDQogIGZpbHRlcih5ZWFySUQgPCAxODk1KSAlPiUNCiAgc2VsZWN0KFNsdWdQY3QpDQoNCmhpdHRlcnMyIDwtIGJhdHRpbmcxICU+JQ0KICBmaWx0ZXIoeWVhcklEID4gMTg5NCwgeWVhcklEIDwgMTkyMSkgJT4lDQogIHNlbGVjdChTbHVnUGN0KQ0KDQpoaXR0ZXJzMyA8LSBiYXR0aW5nMSAlPiUNCiAgZmlsdGVyKHllYXJJRCA+IDE5MjAsIHllYXJJRCA8IDE5NjkpICU+JQ0KICBzZWxlY3QoU2x1Z1BjdCkNCg0KaGl0dGVyczQgPC0gYmF0dGluZzEgJT4lDQogIGZpbHRlcih5ZWFySUQgPiAxOTY5KSAlPiUNCiAgc2VsZWN0KFNsdWdQY3QpDQojT3JnYW5pemluZyA0IGRpZmZlcmVudCBkYXRhc2V0cyBsb29raW5nIGF0IHNsdWdnaW5nIHBlcmNlbnRhZ2UgZm9yIHRoZSBmb2xsb3dpbmcgYm94cGxvdHMuIEFsbCBvZiB0aGVzZSBhcmUgc29tZXdoYXQgZGlmZmVyZW50IGVyYXMsIHdpdGggdGhlIG1vc3QgZHJhbWF0aWMgc3BsaXQgYmVpbmcgZnJvbSBiZWZvcmUgMTkyMCAocHJlLUJhYmUgUnV0aCkgYW5kIGFmdGVyIDE5MjAgKGR1cmluZyBhbmQgcG9zdC1CYWJlIFJ1dGgpDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGhpdHRlcnMxLA0KICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSBsYXRlIDE4NzEgLSAxODk0IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gImJsdWUiLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoaGl0dGVyczIsIA0KICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSAxODk1LTE5MjAiLA0KICAgICAgICB5bGFiID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UiLA0KICAgICAgICBjb2wgPSAieWVsbG93IiwNCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGhpdHRlcnMzLCANCiAgICAgICAgbWFpbiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIGZyb20gMTkyMS0xOTY4IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gInJlZCIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChoaXR0ZXJzNCwgDQogICAgICAgIG1haW4gPSAiU2x1Z2dpbmcgcGVyY2VudGFnZSBmcm9tIDE5NjkgLSBwcmVzZW50IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gInJlZCIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQ0KYGBgDQoNCg0KYGBge3J9DQpzYXBwbHkoaGl0dGVyczEsIG1lYW4sIG5hLnJtID0gVCkNCnNhcHBseShoaXR0ZXJzMiwgbWVhbiwgbmEucm0gPSBUKQ0Kc2FwcGx5KGhpdHRlcnMzLCBtZWFuLCBuYS5ybSA9IFQpDQpzYXBwbHkoaGl0dGVyczQsIG1lYW4sIG5hLnJtID0gVCkNCiNOb3RpY2UgdGhhdCBnaWdhbnRpYyBpbmNyZWFzZSBiZXR3ZWVuIGhpdHRlcnMyIGFuZCBoaXR0ZXJzMw0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShoaXR0ZXJzMSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaGl0dGVyczIpDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KGhpdHRlcnMzKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShoaXR0ZXJzNCkNCmBgYA0KDQpgYGB7cn0NCiNLZWVwIGJhdHRpbmcgc3RhdHMgdGhhdCB3ZSB3YW50IGZvciBwYWlycy4NCmJhdHRpbmdfbnVtIDwtIGJzdGF0cyAlPiUNCiAgZmlsdGVyKFBBID49IDE1MCkgJT4lDQogIHNlbGVjdCgiQkEiLCAnT0JQJywgJ1NsdWdQY3QnLCAiU08iLCAiQkIiLCAiSFIiKQ0KICANCmBgYA0KDQpgYGB7cn0NCnBhaXJzKGJhdHRpbmdfbnVtKQ0KYGBgDQojIyMjIENhcmVlciBCYXR0aW5nIFN0YXRzDQpgYGB7cn0NCmNhcmVlckJhdHRpbmcgPC0gbmEub21pdChic3RhdHMpDQpgYGANCg0KYGBge3J9DQpjYXJlZXJCYXR0aW5nIDwtIGNhcmVlckJhdHRpbmcgJT4lDQogIHNlbGVjdChwbGF5ZXJJRCwgQkEsIFBBLCBTbHVnUGN0LCBPQlAsIFNPLCBIUikgJT4lDQogIGdyb3VwX2J5KHBsYXllcklEKSAlPiUNCiAgc3VtbWFyaXNlX2FsbCgnbWVhbicpDQpgYGANCg0KYGBge3J9DQpjYXJlZXJCYXR0aW5nX251bSA8LSBjYXJlZXJCYXR0aW5nICU+JQ0KICBmaWx0ZXIoUEEgPj0gMTUwKSAlPiUNCiAgc2VsZWN0KEJBLCBQQSwgU2x1Z1BjdCwgT0JQLCBTTywgSFIpDQoNCnBhaXJzKGNhcmVlckJhdHRpbmdfbnVtKQ0KYGBgDQpgYGB7cn0NCmNvcnJtYXRyaXggPC0gY29yKGJhdHRpbmdfbnVtKQ0KY29ycnBsb3QoY29ycm1hdHJpeCwgbWV0aG9kID0gJ251bWJlcicpICNHaXZlcyB1cyBjb3JyZWxhdGlvbiBmcm9tIHBhaXJzIGdyYXBoLg0KYGBgDQoNCmBgYHtyfQ0KY2FyZWVyQmF0dGluZ19udW0xIDwtIGNhcmVlckJhdHRpbmdfbnVtICU+JQ0KICBmaWx0ZXIoUEEgPiA1MDApDQpgYGANCg0KDQojIyAwLWRpbWVuc2lvbmFsIFJlZHVjdGlvbiAoTGVzc29uIDQpDQoNCg0KIyMjIyBCb290c3RyYXBwaW5nDQoNCiMjIFBDQSAoTGVzc29uIDQpDQpgYGB7cn0NCnJlcyA8LSBiYXR0aW5nX251bSAlPiUgcHJjb21wKHNjYWxlID0gVFJVRSkNCnJlcw0KYGBgDQoNCmBgYHtyfQ0KbG9hZGluZ3MgPC0gcmVzJHJvdGF0aW9uDQpsb2FkaW5ncw0KYGBgDQoNCmBgYHtyfQ0Kc2NvcmVfbWF0IDwtIHJlcyR4DQpzY29yZV9tYXQNCmBgYA0KDQoNCmBgYHtyfQ0KZ2V0X2VpZyhyZXMpDQpgYGANCg0KIyMjIyBTY3JlZXBsb3QNCmBgYHtyfQ0KZ2V0X2VpZyhyZXMpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxOjYsIHkgPSBjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnQpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODApICsNCiAgeGxhYigiUHJpbmNpcGFsIENvbXBvbmVudCIpICsNCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBWYXJpYW5jZSBFeHBsYWluZWQiKSArDQogIGdndGl0bGUoIlNjcmVlIFBsb3Qgb2YgUHJpbmNpcGFsIENvbXBvbmVudCBmb3IgQmF0dGluZyBTdGF0aXN0aWNzIikNCmBgYA0KDQoyIFByaW5jaXBhbCBDb21wb25lbnRzOiBQQzEgYW5kIFBDMg0KDQpgYGB7cn0NCmZ2aXpfc2NyZWVwbG90KHJlcywgbWFpbiA9ICJTY3JlZSBQbG90IikNCmBgYA0KDQpDYW4gSWRlbnRpZnkgYW4gZWxib3cgaW4gMy4NCg0KIyMjIyBCaXBsb3QNCmBgYHtyfQ0KcmVzICU+JQ0KICBmdml6X3BjYV92YXIoYXhlcyA9IGMoMSwyKSwNCiAgICAgICAgICAgICAgIGNvbC52YXIgPSAiY29udHJpYiIsDQogICAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwNCiAgICAgICAgICAgICAgIHJlcGVsID0gVFJVRQ0KICAgICAgICAgICAgICAgKQ0KYGBgDQoNCg0KIyMgQ2x1c3RlciBBbmFseXNpcyAoTGVzc29uIDUpDQpgYGB7cn0NCiNOT1QgQ09NUExFVEUhISEhISBUaGlzIHdhcyBqdXN0IGEgdGVzdCwgYnN0YXRzIGlzIHdheSB0b28gYmlnLg0KYnN0YXRzX2Jlc3QgPC0gYnN0YXRzICU+JQ0KICBmaWx0ZXIoUEEgPj0gNjAwKQ0KDQpldV9kaXN0IDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gJ2V1Y2xpZGVhbicpDQpgYGANCg0KYGBge3J9DQpoY19jb21wbGV0ZSA8LSBoY2x1c3QoZXVfZGlzdCwgbWV0aG9kID0gJ2NvbXBsZXRlJykNCg0KcGxvdChoY19jb21wbGV0ZSkNCmBgYA0KDQojIyMjIFNpbGhvdWV0dGUNCg0KYGBge3J9DQpyZXNfdGVzdCA8LSBjYXJlZXJCYXR0aW5nX251bTEgJT4lIGttZWFucyg3KQ0KICBzdHIocmVzX3Rlc3QpDQpgYGANCg0KDQpgYGB7cn0NCmRpc3RhbmNlIDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gImV1Y2xpZGVhbiIpDQpzaWwgPC0gc2lsaG91ZXR0ZSh4ID0gcmVzX3Rlc3QkY2x1c3RlciwgZGlzdCA9IGRpc3RhbmNlKQ0Kc3VtbWFyeShzaWwpDQpzaWwgJT4lIGhlYWQoKQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9zaWxob3VldHRlKHNpbCkNCmBgYA0KDQpgYGB7cn0NCmZ2aXpfbmJjbHVzdChjYXJlZXJCYXR0aW5nX251bTEsIGhjdXQsIGhjX21ldGhvZCA9ICJjb21wbGV0ZSIsIGhjX21ldHJpYyA9ICJldWNsaWRlYW4iLCBtZXRob2QgPSAid3NzIikNCmBgYA0KDQpgYGB7cn0NCiMjVGhpcyBpcyB0byB0ZXN0IG90aGVyIHZhbHVlcyBvZiBLIGZvciB0aGUgc2lsaG91ZXR0ZSBtZXRob2QuDQpyZXNfdGVzdDEgPC0gY2FyZWVyQmF0dGluZ19udW0xICU+JSBrbWVhbnMoMTAgKQ0KICBzdHIocmVzX3Rlc3QxKQ0KYGBgDQoNCg0KYGBge3J9DQpkaXN0YW5jZSA8LSBnZXRfZGlzdChjYXJlZXJCYXR0aW5nX251bTEsIG1ldGhvZD0iZXVjbGlkZWFuIikNCnNpbCA8LSBzaWxob3VldHRlKHggPSByZXNfdGVzdDEkY2x1c3RlciwgZGlzdCA9IGRpc3RhbmNlKQ0Kc3VtbWFyeShzaWwpDQpzaWwgJT4lIGhlYWQoKQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9zaWxob3VldHRlKHNpbCkNCmBgYA0KDQoNCiMjIyMgRGlhbmENCg0KIyMgTGluZWFyIFJlZ3Jlc3Npb24gKExlc3NvbiA2KQ0KDQpMaW5lYXIgUmVncmVzc2lvbiBjb21wYXJpbmcgdGVhbSBwYXlyb2xsIGFuZCB3aW4gcmF0ZS4NCmBgYHtyfQ0KdGVhbXMgPSBhcy5kYXRhLnRhYmxlKFRlYW1zKQ0KdGVhbXMgPSB0ZWFtc1ssIC4oeWVhcklELA0KICAgICAgICAgICAgICAgICAgbGdJRCA9IGFzLmNoYXJhY3RlcihsZ0lEKSwNCiAgICAgICAgICAgICAgICAgIHRlYW1JRCA9IGFzLmNoYXJhY3Rlcih0ZWFtSUQpLA0KICAgICAgICAgICAgICAgICAgZnJhbmNoSUQgPSBhcy5jaGFyYWN0ZXIoZnJhbmNoSUQpLA0KICAgICAgICAgICAgICAgICAgUmFuaywgRywgVywgTCwgUiwgRVJBLCBTTywNCiAgICAgICAgICAgICAgICAgIFdpblBlcmNlbnQgPSBXLyhXK0wpKV0NCg0Kc2FsYXJpZXMgPSBhcy5kYXRhLnRhYmxlKFNhbGFyaWVzKQ0Kc2FsYXJpZXMgPSBzYWxhcmllc1ssIGMoImxnSUQiLCAidGVhbUlEIiwgInNhbGFyeTFNIikgOj0NCiAgICAgICAgICAgICAgICAgICAgICBsaXN0KGFzLmNoYXJhY3RlcihsZ0lEKSwgYXMuY2hhcmFjdGVyKHRlYW1JRCksIHNhbGFyeSAvIDFlNkwpXQ0KcGF5cm9sbCA9IHNhbGFyaWVzWywgLihwYXlyb2xsID0gc3VtKHNhbGFyeTFNKSksIGJ5PS4odGVhbUlELCB5ZWFySUQpXQ0KdGVhbVBheXJvbGwgPSBtZXJnZSh0ZWFtcywgcGF5cm9sbCwgYnkgPSBjKCJ0ZWFtSUQiLCAieWVhcklEIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHRlYW1QYXlyb2xsLCBhZXMoeCA9IHBheXJvbGwsIHkgPSBXaW5QZXJjZW50KSkgKyBnZW9tX3BvaW50KCkgICsgbGFicyh4ID0gIlBheXJvbGwgKGluIG1pbGxpb25zKSIsIHkgPSAiV2luIFBlcmNlbnRhZ2UiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBzZSA9IEZBTFNFKQ0KDQpgYGANCmBgYHtyfQ0KbW9kX2xtIDwtIGxtKGRhdGEgPSB0ZWFtUGF5cm9sbCwgV2luUGVyY2VudH5wYXlyb2xsKQ0KbW9kX2xtDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9sbSkNCmBgYA0KYGBge3J9DQpwYXlyb2xsX3ByZWQgPC0gdGVhbVBheXJvbGwgJT4lDQogIGFkZF9wcmVkaWN0aW9ucyhtb2RfbG0pDQoNCnBheXJvbGxfcHJlZCAlPiUNCiAgZmlsdGVyKHllYXJJRCA+PSAyMDEwKSAlPiUNCiAgYXJyYW5nZShkZXNjKHByZWQpKSAlPiUNCiAgaGVhZCgyNSkNCmBgYA0KYGBge3J9DQpwYXlyb2xsX3ByZWQgJT4lDQogIGZpbHRlcih5ZWFySUQgPj0gMjAxMCkgJT4lDQogIGFycmFuZ2UoZGVzYyhXaW5QZXJjZW50KSkgJT4lDQogIGhlYWQoMjUpDQpgYGANCk9ubHkgZml2ZSB0ZWFtcyBhcmUgaW4gdGhlIHRvcCAyNSBvZiBib3RoIHBheXJvbGwgYW5kIHdpbiBwZXJjZW50YWdlIGluIHRoZSAyMDEwcy4gVGhlc2UgdGVhbXMgYXJlIHRoZSAyMDExIFBoaWxsaWVzLCAyMDExIFlhbmtlZXMsIDIwMTAgWWFua2VlcywgMjAxMiBZYW5rZWVzLCBhbmQgMjAxNiBSYW5nZXJzLiBUaGlzIHNob3dzIHRoYXQgc3BlbmRpbmcgdGhlIG1vc3QgbW9uZXkgZG9lc24ndCBhdXRvbWF0aWNhbGx5IG1lYW4geW91IGFyZSBnZXR0aW5nIHRoZSBiZXN0IHByb2R1Y3Qgb24gdGhlIGZpZWxkLg0KIyMgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uDQoNCiMjIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uDQpgYGB7cn0NCmJzdGF0c19zYWxhcnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUNCiAgZmlsdGVyKFBBID49IDEwMCkgJT4lDQogIGZpbHRlcihzYWxhcnkgPiA1MDAwMDApDQpgYGANCg0KYGBge3J9DQpic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSA8LSBic3RhdHNfc2FsYXJ5ICU+JQ0KICBmaWx0ZXIoeWVhcklEID49IDIwMDIpDQpgYGANCg0KDQpgYGB7cn0NCmxtX21vZCA8LSBsbShzYWxhcnkgfiBILCBIUiwgZGF0YSA9IGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5KQ0Kc3VtbWFyeShsbV9tb2QpDQpgYGANCg0KYGBge3J9DQpsbV9tb2RfcHJkIDwtIGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5ICU+JSBhZGRfcHJlZGljdGlvbnMobG1fbW9kKQ0KbG1fbW9kX3ByZA0KYGBgDQoNCmBgYHtyfQ0KZnVsbF9tb2RlbCA8LSBsbShzYWxhcnkgfi4sIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSkNCnN1bW1hcnkoZnVsbF9tb2RlbCkNCmBgYA0KDQpgYGB7cn0NCmZ1bGxfbW9kZWxfcHJlZCA8LSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgYWRkX3ByZWRpY3Rpb25zKGZ1bGxfbW9kZWwpDQpmdWxsX21vZGVsX3ByZWQNCmBgYA0KDQpgYGB7cn0NCmFkdl9zdGF0X21vZCA8LSBsbShzYWxhcnkgfiBPUFMsIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSkNCnN1bW1hcnkoYWR2X3N0YXRfbW9kKQ0KYGBgDQoNCg0KIyMgUmVzYW1wbGluZyBNZXRob2RzDQoNCmBgYHtyfQ0KI2luY2x1ZGluZyAyMDAyIGFuZCB1cCBiZWNhdXNlIHNhbGFyeSBiZWNvbWVzIGhpZ2hlcg0KYnN0YXRzX3NhbGFyeV8yMWNlbnR1cnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUNCiAgZmlsdGVyKHllYXJJRCA+PSAyMDAyKQ0KYGBgDQoNCg0KYGBge3J9DQpic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgaGVhZCgxMCkNCmBgYA0KDQoNCg0KYGBge3J9DQojIHNldHRpbmcgc2VlZCB0byBnZW5lcmF0ZSBhIHJlcHJvZHVjaWJsZSByYW5kb20gc2FtcGxpbmcNCnNldC5zZWVkKDEyMykNCiANCiMgZGVmaW5pbmcgdHJhaW5pbmcgY29udHJvbCBhcyBjcm9zcy12YWxpZGF0aW9uIGFuZCB2YWx1ZSBvZiBLIGVxdWFsIHRvIDEwDQp0cmFpbl9jb250cm9sIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyID0gMTApDQoNCiMgdHJhaW5pbmcgdGhlIG1vZGVsDQptb2RlbCA8LSB0cmFpbihzYWxhcnkgfiBPQlAsIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSwNCiAgICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbl9jb250cm9sKQ0KDQpwcmludChtb2RlbCkNCmBgYA0KDQoNCiMjIEZlYXR1cmUgU2VsZWN0aW9uDQpgYGB7cn0NCmJzdGF0c19zYWxhcnlfbnVtdmFycyA8LSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgDQogIHNlbGVjdChjKDY6MzIpKQ0KYGBgDQoNCmBgYHtyfQ0KI0NvcnJlbGF0aW9uIG1hcHBpbmcgDQoNCiNtYWtpbmcgY29ycmVsYXRpb24gaGVhdCBtYXAgDQpjb3JyX251bWVyaWMgPC0gcm91bmQoY29yKGJzdGF0c19zYWxhcnlfbnVtdmFycyksIDEpDQoNCiNwbG90IHRvIHZpc3VhbGl6ZSB0aGUgY29ycmVsYXRpb25zIA0KZ2djb3JycGxvdChjb3JyX251bWVyaWMsDQogICAgICAgICAgIHR5cGUgPSAibG93ZXIiLA0KICAgICAgICAgICBsYWIgPSBUUlVFLCANCiAgICAgICAgICAgbGFiX3NpemUgPSAyLCAgDQogICAgICAgICAgIGNvbG9ycyA9IGMoInRvbWF0bzIiLCAid2hpdGUiLCAic3ByaW5nZ3JlZW4zIiksDQogICAgICAgICAgIHRpdGxlPSJDb3JyZWxvZ3JhbSBvZiBiYXR0aW5nIERhdGEiLCANCiAgICAgICAgICAgZ2d0aGVtZT10aGVtZV9idykNCmBgYA0KDQpgYGB7cn0NCnJlZ2ZpdC5mdWxsID0gcmVnc3Vic2V0cyhzYWxhcnkgfi4sIGRhdGEgPSBic3RhdHNfc2FsYXJ5X251bXZhcnMsICBudm1heCA9IDEzLCBtZXRob2Q9ImV4aGF1c3RpdmUiKQ0Kc3VtbWFyeShyZWdmaXQuZnVsbCkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkocmVnZml0LmZ1bGwpJHJzcQ0KYGBgDQoNCg0KDQpgYGB7cn0NCnBsb3Qoc3VtbWFyeShyZWdmaXQuZnVsbCkkcnNxKQ0KYGBgDQoNCmBgYHtyfQ0KcmVnLnN1bW1hcnkgPC0gc3VtbWFyeShyZWdmaXQuZnVsbCkgI2dldCB0aGUgc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygyLDIpKQ0KI3JzcyBwbG90IC0gIE5PVCBVU0VGVUwNCnBsb3QocmVnLnN1bW1hcnkkcnNzICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iUlNTIix0eXBlPSJsIikNCg0KI2FkanIyIHBsb3QNCnBsb3QocmVnLnN1bW1hcnkkYWRqcjIgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIiwgeWxhYj0iQWRqdXN0ZWQgUlNxIix0eXBlPSJsIikNCg0KbWF4X2FkanIyIDwtIHdoaWNoLm1heChyZWcuc3VtbWFyeSRhZGpyMikNCnBvaW50cyhtYXhfYWRqcjIscmVnLnN1bW1hcnkkYWRqcjJbbWF4X2FkanIyXSwgY29sPSJyZWQiLGNleD0yLHBjaD0yMCkNCg0KIyBBSUMgY3JpdGVyaW9uIChDcCkgdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkY3AgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJDcCIsIHR5cGU9J2wnKQ0KDQptaW5fY3AgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGNwICkNCnBvaW50cyhtaW5fY3AsIHJlZy5zdW1tYXJ5JGNwW21pbl9jcF0sY29sPSJyZWQiLGNleD0yLHBjaD0yMCkNCg0KIyBCSUMgY3JpdGVyaW9uIHRvIG1pbmltaXplDQpwbG90KHJlZy5zdW1tYXJ5JGJpYyAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IkJJQyIsdHlwZT0nbCcpDQoNCm1pbl9iaWMgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGJpYykNCnBvaW50cyhtaW5fYmljLHJlZy5zdW1tYXJ5JGJpY1ttaW5fYmljXSxjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KYGBgDQoNCmBgYHtyfQ0KI0ZvcndhcmQgc3RlcHdpc2Ugc2VsZWN0aW9uDQpyZWdmaXQuZndkID0gcmVnc3Vic2V0cyhzYWxhcnkgfi4gLCBkYXRhPWJzdGF0c19zYWxhcnlfbnVtdmFycywgbnZtYXg9MTMsIG1ldGhvZCA9ImZvcndhcmQiKQ0Kc3VtbWFyeShyZWdmaXQuZndkKQ0KYGBgDQoNCmBgYHtyfQ0KcmVnLnN1bW1hcnkgPC0gc3VtbWFyeShyZWdmaXQuZndkKSAjZ2V0IHRoZSBzdW1tYXJ5DQoNCnBhcihtZnJvdz1jKDIsMikpDQojcnNzIHBsb3QgLSAgTk9UIFVTRUZVTA0KcGxvdChyZWcuc3VtbWFyeSRyc3MgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJSU1MiLHR5cGU9ImwiKQ0KDQojYWRqcjIgcGxvdA0KcGxvdChyZWcuc3VtbWFyeSRhZGpyMiAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLCB5bGFiPSJBZGp1c3RlZCBSU3EiLHR5cGU9ImwiKQ0KDQptYXhfYWRqcjIgPC0gd2hpY2gubWF4KHJlZy5zdW1tYXJ5JGFkanIyKQ0KcG9pbnRzKG1heF9hZGpyMixyZWcuc3VtbWFyeSRhZGpyMlttYXhfYWRqcjJdLCBjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KDQojIEFJQyBjcml0ZXJpb24gKENwKSB0byBtaW5pbWl6ZQ0KcGxvdChyZWcuc3VtbWFyeSRjcCAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IkNwIiwgdHlwZT0nbCcpDQoNCm1pbl9jcCA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkY3AgKQ0KcG9pbnRzKG1pbl9jcCwgcmVnLnN1bW1hcnkkY3BbbWluX2NwXSxjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KDQojIEJJQyBjcml0ZXJpb24gdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkYmljICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iQklDIix0eXBlPSdsJykNCg0KbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQ0KcG9pbnRzKG1pbl9iaWMscmVnLnN1bW1hcnkkYmljW21pbl9iaWNdLGNvbD0icmVkIixjZXg9MixwY2g9MjApDQpgYGANCg0KYGBge3J9DQojQmFja3dhcmRzIHN0ZXB3aXNlIHNlbGVjdGlvbg0KcmVnZml0LmJ3ZCA9IHJlZ3N1YnNldHMoc2FsYXJ5IH4uICwgZGF0YT1ic3RhdHNfc2FsYXJ5X251bXZhcnMsbnZtYXg9MTMsIG1ldGhvZCA9ImJhY2t3YXJkIikNCnN1bW1hcnkocmVnZml0LmJ3ZCkNCmBgYA0KDQpgYGB7cn0NCnJlZy5zdW1tYXJ5IDwtIHN1bW1hcnkocmVnZml0LmJ3ZCkgI2dldCB0aGUgc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygyLDIpKQ0KI3JzcyBwbG90IC0gIE5PVCBVU0VGVUwNCnBsb3QocmVnLnN1bW1hcnkkcnNzICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iUlNTIix0eXBlPSJsIikNCg0KI2FkanIyIHBsb3QNCnBsb3QocmVnLnN1bW1hcnkkYWRqcjIgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIiwgeWxhYj0iQWRqdXN0ZWQgUlNxIix0eXBlPSJsIikNCg0KbWF4X2FkanIyIDwtIHdoaWNoLm1heChyZWcuc3VtbWFyeSRhZGpyMikNCnBvaW50cyhtYXhfYWRqcjIsIHJlZy5zdW1tYXJ5JGFkanIyW21heF9hZGpyMl0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkNCg0KIyBBSUMgY3JpdGVyaW9uIChDcCkgdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkY3AgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJDcCIsIHR5cGU9J2wnKQ0KDQptaW5fY3AgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGNwICkNCnBvaW50cyhtaW5fY3AsIHJlZy5zdW1tYXJ5JGNwW21pbl9jcF0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkNCg0KIyBCSUMgY3JpdGVyaW9uIHRvIG1pbmltaXplDQpwbG90KHJlZy5zdW1tYXJ5JGJpYywgeGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLCB5bGFiPSJCSUMiLCB0eXBlPSdsJykNCg0KbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQ0KcG9pbnRzKG1pbl9iaWMsIHJlZy5zdW1tYXJ5JGJpY1ttaW5fYmljXSwgY29sPSJyZWQiLCBjZXg9MiwgcGNoPTIwKQ0KYGBgDQoNCmBgYHtyfQ0KI3JpZGdlIHJlZ3Jlc3Npb24gDQoNCiMgZ2V0dGluZyB0aGUgcHJlZGljdG9ycw0KeF92YXIgPC0gYnN0YXRzX3NhbGFyeV9udW12YXJzICU+JSBzZWxlY3QoLXNhbGFyeSkgJT4lIGFzLm1hdHJpeCgpDQojIGdldHRpbmcgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlDQp5X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnNbLCJzYWxhcnkiXQ0KYGBgDQoNCmBgYHtyfQ0KcmlkZ2UgPC0gZ2xtbmV0KHhfdmFyLCB5X3ZhciwgYWxwaGE9MCkNCnN1bW1hcnkocmlkZ2UpDQpgYGANCg0KYGBge3J9DQpjdl9yaWRnZSA8LSBjdi5nbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYSA9IDApDQpjdl9yaWRnZQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdChjdl9yaWRnZSkNCmBgYA0KDQpgYGB7cn0NCmN2X3JpZGdlJGxhbWJkYS5taW4NCmBgYA0KDQpgYGB7cn0NCmN2X3JpZGdlJGxhbWJkYS4xc2UNCmBgYA0KDQpgYGB7cn0NCmxic19mdW4gPC0gZnVuY3Rpb24oZml0LCBvZmZzZXRfeD0xLCAuLi4pIHsNCiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkNCiAgeCA8LSBsb2coZml0JGxhbWJkYVtMXSkgKyBvZmZzZXRfeA0KICB5IDwtIGZpdCRiZXRhWyAsTF0NCiAgbGFicyA8LSBuYW1lcyh5KQ0KICB0ZXh0KHgsIHksIGxhYmVscz1sYWJzLCAuLi4pDQp9DQoNCnBsb3QocmlkZ2UsIHh2YXIgPSAibGFtYmRhIiwgbGFiZWw9VCkNCmxic19mdW4ocmlkZ2UpICMgYWRkIG5hbW5lcw0KDQphYmxpbmUodiA9IGxvZyhjdl9yaWRnZSRsYW1iZGEubWluKSwgY29sID0gInJlZCIsIGx0eT0yKSAjbGFtYmRhLm1pbg0KYWJsaW5lKHYgPSBsb2coY3ZfcmlkZ2UkbGFtYmRhLjFzZSksIGNvbD0iYmx1ZSIsIGx0eT0yKSAgI2xhbWJkYS4xc2UNCmBgYA0KDQpgYGB7cn0NCm1pbl9yaWRnZSA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0wLCBsYW1iZGEgPSBjdl9yaWRnZSRsYW1iZGEubWluKQ0KY29lZihtaW5fcmlkZ2UpDQpgYGANCg0KYGBge3J9DQojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3QgZGF0YQ0KcHJlZGljdGlvbnMgPC0gbWluX3JpZGdlICU+JSBwcmVkaWN0KHhfdmFyKSAlPiUgYXMudmVjdG9yKCkNCg0KIyBNb2RlbCBwZXJmb3JtYW5jZSBtZXRyaWNzDQpkYXRhLmZyYW1lKA0KICBSTVNFID0gUk1TRShwcmVkaWN0aW9ucywgeV92YXIpLA0KICBSc3F1YXJlID0gUjIocHJlZGljdGlvbnMsIHlfdmFyKQ0KKQ0KYGBgDQoNCmBgYHtyfQ0KIyBMYXNzbyANCg0KIyBnZXR0aW5nIHRoZSBwcmVkaWN0b3JzDQp4X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnMgJT4lIHNlbGVjdCgtc2FsYXJ5KSAlPiUgYXMubWF0cml4KCkNCiMgZ2V0dGluZyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUNCnlfdmFyIDwtIGJzdGF0c19zYWxhcnlfbnVtdmFyc1ssInNhbGFyeSJdDQpgYGANCg0KDQpgYGB7cn0NCmxhc3NvIDwtIGdsbW5ldCh4X3ZhciwgeV92YXIsIGFscGhhPTEpDQpzdW1tYXJ5KGxhc3NvKQ0KYGBgDQoNCmBgYHtyfQ0KY3ZfbGFzc28gPC0gY3YuZ2xtbmV0KHhfdmFyLCB5X3ZhciwgYWxwaGEgPSAxKQ0KY3ZfbGFzc28NCmBgYA0KDQpgYGB7cn0NCnBsb3QoY3ZfbGFzc28pDQpgYGANCg0KDQpgYGB7cn0NCmxic19mdW4gPC0gZnVuY3Rpb24oZml0LCBvZmZzZXRfeD0xLCAuLi4pIHsNCiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkNCiAgeCA8LSBsb2coZml0JGxhbWJkYVtMXSkrIG9mZnNldF94DQogIHkgPC0gZml0JGJldGFbLCBMXQ0KICBsYWJzIDwtIG5hbWVzKHkpDQogIHRleHQoeCwgeSwgbGFiZWxzPWxhYnMsIC4uLikNCn0NCnBsb3QobGFzc28sIHh2YXIgPSAibGFtYmRhIiwgbGFiZWw9VCkNCmxic19mdW4obGFzc28pDQoNCmFibGluZSh2PWxvZyhjdl9sYXNzbyRsYW1iZGEubWluKSwgY29sID0gInJlZCIsIGx0eT0yKQ0KYWJsaW5lKHY9bG9nKGN2X2xhc3NvJGxhbWJkYS4xc2UpLCBjb2w9ImJsdWUiLCBsdHk9MikNCmBgYA0KDQpgYGB7cn0NCm1pbl9sYXNzbyA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0xLCBsYW1iZGEgPSBjdl9sYXNzbyRsYW1iZGEubWluKQ0KY29lZihtaW5fbGFzc28pDQpgYGANCg0KYGBge3J9DQpzZV9sYXNzbyA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0xLCBsYW1iZGEgPSBjdl9sYXNzbyRsYW1iZGEuMXNlKQ0KY29lZihzZV9sYXNzbykNCmBgYA0KDQpgYGB7cn0NCiMgTWFrZSBwcmVkaWN0aW9ucyBvbiB0aGUgdGVzdCBkYXRhDQpwcmVkaWN0aW9ucyA8LSBtaW5fbGFzc28gJT4lIHByZWRpY3QoeF92YXIpICU+JSBhcy52ZWN0b3IoKQ0KIyBNb2RlbCBwZXJmb3JtYW5jZSBtZXRyaWNzDQpkYXRhLmZyYW1lKA0KICBSTVNFID0gUk1TRShwcmVkaWN0aW9ucywgeV92YXIpLA0KICBSc3F1YXJlID0gUjIocHJlZGljdGlvbnMsIHlfdmFyKQ0KKQ0KYGBgDQoNCg0KDQojIyBTYWxhcnkgRGF0YQ0KYGBge3J9DQpmcmFuY2hpc2UgPC0gYyhgQU5BYCA9ICJMQUEiLCBgQVJJYCA9ICJBUkkiLCBgQVRMYCA9ICJBVEwiLCANCiAgICAgICAgICAgICAgIGBCQUxgID0gIkJBTCIsIGBCT1NgID0gIkJPUyIsIGBDQUxgID0gIkxBQSIsDQogICAgICAgICAgICAgICBgQ0hBYCA9ICJDSEEiLCBgQ0hOYCA9ICJDSE4iLCBgQ0lOYCA9ICJDSU4iLCANCiAgICAgICAgICAgICAgIGBDTEVgID0gIkNMRSIsIGBDT0xgID0gIkNPTCIsIGBERVRgID0gIkRFVCIsIA0KICAgICAgICAgICAgICAgYEZMT2AgPSAiTUlBIiwgYEhPVWAgPSAiSE9VIiwgYEtDQWAgPSAiS0NBIiwgDQogICAgICAgICAgICAgICBgTEFBYCA9ICJMQUEiLCBgTEFOYCA9ICJMQU4iLCBgTUlBYCA9ICJNSUEiLCANCiAgICAgICAgICAgICAgIGBNSUxgID0gIk1JTCIsIGBNSU5gID0gIk1JTiIsIGBNTDRgID0gIk1JTCIsIA0KICAgICAgICAgICAgICAgYE1PTmAgPSAiV0FTIiwgYE5ZQWAgPSAiTllBIiwgYE5ZTWAgPSAiTllOIiwgDQogICAgICAgICAgICAgICBgTllOYCA9ICJOWU4iLCBgT0FLYCA9ICJPQUsiLCBgUEhJYCA9ICJQSEkiLCANCiAgICAgICAgICAgICAgIGBQSVRgID0gIlBJVCIsIGBTRE5gID0gIlNETiIsIGBTRUFgID0gIlNFQSIsDQogICAgICAgICAgICAgICBgU0ZHYCA9ICJTRk4iLCBgU0ZOYCA9ICJTRk4iLCBgU0xOYCA9ICJTTE4iLCANCiAgICAgICAgICAgICAgIGBUQkFgID0gIlRCQSIsIGBURVhgID0gIlRFWCIsIGBUT1JgID0gIlRPUiIsDQogICAgICAgICAgICAgICBgV0FTYCA9ICJXQVMiKQ0KYGBgDQoNCmBgYHtyfQ0KU2FsYXJpZXMkZnJhbmNoaXNlIDwtIHVubmFtZShmcmFuY2hpc2VbU2FsYXJpZXMkdGVhbUlEXSkNCmBgYA0KDQoNCmBgYHtyfQ0KYXZnX3RlYW1fc2FsYXJpZXMgPC0gU2FsYXJpZXMgJT4lDQogICAgZ3JvdXBfYnkoeWVhcklELCBmcmFuY2hpc2UsIGxnSUQpICU+JQ0KICAgIHN1bW1hcmlzZShzYWxhcnkgPSBtZWFuKHNhbGFyeSkvMWU2KSAlPiUNCiAgICBmaWx0ZXIoIShmcmFuY2hpc2UgPT0gIkNMRSIgJiBsZ0lEID09ICJOTCIpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGF2Z190ZWFtX3NhbGFyaWVzLCANCiAgICAgICBhZXMoeCA9IHllYXJJRCwgeSA9IHNhbGFyeSwgZ3JvdXAgPSBmYWN0b3IoZnJhbmNoaXNlKSkpICsNCiAgICAgICBnZW9tX3BhdGgoKSArDQogICAgICAgbGFicyh4ID0gIlllYXIiLCB5ID0gIkF2ZXJhZ2UgdGVhbSBzYWxhcnkgKG1pbGxpb25zIFVTRCkiKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KFNhbGFyaWVzLCBhZXMoeCA9IGZhY3Rvcih5ZWFySUQpLCB5ID0gc2FsYXJ5LzFlNSkpICsNCiAgIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIG91dGxpZXIuc2l6ZSA9IDEpICsNCiAgIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJTYWxhcnkgKHBlciAkMSwwMDAsMDAwKSIpICsNCiAgIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCmBgYHtyfQ0KYXZnX3RlYW1fc2FsYXJpZXMxIDwtIFNhbGFyaWVzICU+JQ0KICAgIGdyb3VwX2J5KHllYXJJRCwgZnJhbmNoaXNlLCBsZ0lEKSAlPiUNCiAgICBzdW1tYXJpc2Uoc2FsYXJ5PSBtZWFuKHNhbGFyeSkvMWU2KSAlPiUNCiAgICBmaWx0ZXIoIShmcmFuY2hpc2UgPT0gIkNMRSIgJiBsZ0lEID09ICJOTCIpKSAlPiUNCiAgICBmaWx0ZXIoeWVhcklEID49IDIwMDIpDQoNCmF2Z190ZWFtX3NhbGFyaWVzMSAlPiUNCiAgYXJyYW5nZShkZXNjKHNhbGFyeSkpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoYXZnX3RlYW1fc2FsYXJpZXMxLCBhZXMoeCA9IGZyYW5jaGlzZSwgeSA9IHNhbGFyeSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh4ID0gIlRlYW0iLCB5ID0gIlNhbGFyeSAocGVyICQxMDAsMDAwKSIpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoYXZnX3RlYW1fc2FsYXJpZXMxLCBhZXMoeCA9IGZyYW5jaGlzZSwgeSA9IHNhbGFyeSwgZmlsbCA9IGZyYW5jaGlzZSkpICsNCiAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAxKSArDQogICBsYWJzKHggPSAiWWVhciIsIHkgPSAiQXZlcmFnZSBUZWFtIFNhbGFyeSBTaW5jZSAyMDAyIChwZXIgJDEwLDAwMCwwMDApIikgKw0KICAgY29vcmRfZmxpcCgpDQpgYGANCg0K
=======
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKCkpDQoNCmxpYnJhcnkoTGFobWFuKQ0KbGlicmFyeShtb3NhaWMpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtcGxvdCkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoY2x1c3RlcikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KG1vZCkNCmxpYnJhcnkobW9kZWxyKQ0KbGlicmFyeShsZWFwcykNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KElTTFIyKQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KbGlicmFyeShnbG1uZXQpDQpgYGANCg0KYGBge3J9DQojTG9hZCBpbiBQZW9wbGUsIEJhdHRpbmcsIGFuZCBQaXRjaGluZyBEYXRhZnJhbWVzDQpkYXRhKCJQZW9wbGUiKSANCmRhdGEoIkJhdHRpbmciKQ0KZGF0YSgiUGl0Y2hpbmciKQ0KYGBgDQoNCmBgYHtyfQ0KI01lcmdlcyBwbGF5ZXIgbmFtZSB0byBCYXR0aW5nIGRhdGEuIA0KYnN0YXRzIDwtIGJhdHRpbmdTdGF0cygpDQoJc3RyKGJzdGF0cykNCgkNCg0KUGVvcGxlJG5hbWUgPC0gcGFzdGUoUGVvcGxlJG5hbWVGaXJzdCwgUGVvcGxlJG5hbWVMYXN0LCBzZXAgPSAiICIpDQoNCmJhdHRpbmdfbmFtZSA8LSBtZXJnZShCYXR0aW5nLA0KICAgICAgICAgICAgICAgICBQZW9wbGVbLGMoInBsYXllcklEIiwgIm5hbWUiKV0sDQogICAgICAgICAgICAgICAgIGJ5ID0gInBsYXllcklEIiwgYWxsLnggPSBUUlVFKQ0KDQojTWVyZ2VzIHBsYXllciBuYW1lIHRvIFBpdGNoaW5nIGRhdGEuDQoNClBlb3BsZSRuYW1lIDwtIHBhc3RlKFBlb3BsZSRuYW1lRmlyc3QsIFBlb3BsZSRuYW1lTGFzdCwgc2VwID0gIiAiKQ0KDQpwaXRjaGluZ19uYW1lIDwtIG1lcmdlKFBpdGNoaW5nLA0KICAgICAgICAgICAgICAgICBQZW9wbGVbLGMoInBsYXllcklEIiwgIm5hbWUiKV0sDQogICAgICAgICAgICAgICAgIGJ5ID0gInBsYXllcklEIiwgYWxsLnggPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KI0NyZWF0aW5nIGFkZGl0aW9uYWwgc3RhdHMgZm9yIGJzdGF0cw0KYnN0YXRzW2lzLm5hKGJzdGF0cyldID0gMA0KI2lzLm5hbihic3RhdHMpDQoNCmJzdGF0cyA8LSBic3RhdHMgJT4lDQogIG11dGF0ZShLX1BlcmNlbnQgPSBTTyAvIFBBKSAlPiUNCiAgbXV0YXRlKEJCX1BlcmNlbnQgPSAoQkIgKyBJQkIpIC8gUEEpICU+JQ0KICBtdXRhdGVfYWxsKH5yZXBsYWNlKC4sIGlzLm5hbiguKSwgMCkpDQoNCmBgYA0KDQpgYGB7cn0NCmJzdGF0cyA8LSBic3RhdHMgJT4lDQogIG11dGF0ZV9hdCh2YXJzKEtfUGVyY2VudCwgQkJfUGVyY2VudCksIGZ1bnMocm91bmQoLiwgMykpKQ0KYGBgDQoNCmBgYHtyfQ0KYnN0YXRzX3NhbGFyeSA8LSBic3RhdHMgJT4lDQogICAgICAgICAgICAgIGZpbHRlcih5ZWFySUQgPj0gMTk4NSkgJT4lDQogICAgICAgICAgICAgIGxlZnRfam9pbihzZWxlY3QoU2FsYXJpZXMsIHBsYXllcklELCB5ZWFySUQsIHRlYW1JRCwgc2FsYXJ5KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgYnk9YygicGxheWVySUQiLCAieWVhcklEIiwgInRlYW1JRCIpKQ0KDQpic3RhdHNfc2FsYXJ5W2lzLm5hKGJzdGF0c19zYWxhcnkpXSA9IDANCnN0cihic3RhdHNfc2FsYXJ5KQ0KDQpgYGANCg0KYGBge3J9DQpic3RhdHNfc3VyZSA8LSBic3RhdHNfc2FsYXJ5ICU+JQ0KICBmaWx0ZXIoUEEgPiAxNTApICU+JQ0KICBzZWxlY3QoT1BTLCBCQUJJUCwgS19QZXJjZW50LCBCQl9QZXJjZW50LCBzYWxhcnkpDQpgYGANCg0KIyMgRGF0YSBQcmVwYXJhdGlvbiAoTGVzc29uIDEgJiAyKQ0KDQpgYGB7cn0NCiNLZWVwIHBsYXllcnMgd2l0aCBvdmVyIDE1MCBhdCBiYXRzLiAoV2UgY2FuIGNoYW5nZSB0aGlzIHZhbHVlIGlmIG5lY2Vzc2FyeSkuDQojQ3JlYXRpbmcgYmF0dGluZyBhdmVyYWdlIHZhcmlhYmxlLg0KDQpiYXR0aW5nMSA8LSBic3RhdHMgJT4lDQogIGZpbHRlcihBQiA+PSAxNTApDQogIA0KYGBgDQoNCmBgYHtyfQ0KYnN0YXRzICU+JQ0KICBmaWx0ZXIocGxheWVySUQgPT0gImJvZ2FleGEwMSIpDQpgYGANCg0KIyMgRXhwbG9yYXRvcnkgQW5hbHlzaXMgKExlc3NvbiAxICYgMikNCkxlc3NvbnMgMSBhbmQgMiB3aWxsIGp1c3QgYmUgcGFydHMgb2YgdGhlIG92ZXJhbGwgcHJvamVjdC4gU2ltcGxlIHRoaW5ncyBsaWtlIGRhdGEgbWFuaXB1bGF0aW9uLCBhcHBseSBmdW5jdGlvbnMsIGJveHBsb3RzLCBldGMuIFRoaXMgd2lsbCBiZSBkYXRhIHByZXBhcmF0aW9uIGl0ZW1zIGFuZCBleHBsb3JhdG9yeSBhbmFseXNpcy4NCg0KYGBge3J9DQpiIDwtIGdncGxvdChiYXR0aW5nMSwgYWVzKHggPSB0ZWFtSUQsIHkgPSBIUikpICsNCiAgZ2VvbV9ib3hwbG90KGNvbCA9ICJibGFjayIsIGFlcyhmaWxsID0gdGVhbUlEKSkNCmINCg0KYGBgDQoNCmBgYHtyfQ0KaGl0dGVyczEgPC0gYmF0dGluZzEgJT4lDQogIGZpbHRlcih5ZWFySUQgPCAxODk1KSAlPiUNCiAgc2VsZWN0KFNsdWdQY3QpDQoNCmhpdHRlcnMyIDwtIGJhdHRpbmcxICU+JQ0KICBmaWx0ZXIoeWVhcklEID4gMTg5NCwgeWVhcklEIDwgMTkyMSkgJT4lDQogIHNlbGVjdChTbHVnUGN0KQ0KDQpoaXR0ZXJzMyA8LSBiYXR0aW5nMSAlPiUNCiAgZmlsdGVyKHllYXJJRCA+IDE5MjAsIHllYXJJRCA8IDE5NjkpICU+JQ0KICBzZWxlY3QoU2x1Z1BjdCkNCg0KaGl0dGVyczQgPC0gYmF0dGluZzEgJT4lDQogIGZpbHRlcih5ZWFySUQgPiAxOTY5KSAlPiUNCiAgc2VsZWN0KFNsdWdQY3QpDQojT3JnYW5pemluZyA0IGRpZmZlcmVudCBkYXRhc2V0cyBsb29raW5nIGF0IHNsdWdnaW5nIHBlcmNlbnRhZ2UgZm9yIHRoZSBmb2xsb3dpbmcgYm94cGxvdHMuIEFsbCBvZiB0aGVzZSBhcmUgc29tZXdoYXQgZGlmZmVyZW50IGVyYXMsIHdpdGggdGhlIG1vc3QgZHJhbWF0aWMgc3BsaXQgYmVpbmcgZnJvbSBiZWZvcmUgMTkyMCAocHJlLUJhYmUgUnV0aCkgYW5kIGFmdGVyIDE5MjAgKGR1cmluZyBhbmQgcG9zdC1CYWJlIFJ1dGgpDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGhpdHRlcnMxLA0KICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSBsYXRlIDE4NzEgLSAxODk0IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gImJsdWUiLA0KICAgICAgICBob3Jpem9udGFsID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoaGl0dGVyczIsIA0KICAgICAgICBtYWluID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UgZnJvbSAxODk1LTE5MjAiLA0KICAgICAgICB5bGFiID0gIlNsdWdnaW5nIHBlcmNlbnRhZ2UiLA0KICAgICAgICBjb2wgPSAieWVsbG93IiwNCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGhpdHRlcnMzLCANCiAgICAgICAgbWFpbiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIGZyb20gMTkyMS0xOTY4IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gInJlZCIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChoaXR0ZXJzNCwgDQogICAgICAgIG1haW4gPSAiU2x1Z2dpbmcgcGVyY2VudGFnZSBmcm9tIDE5NjkgLSBwcmVzZW50IiwNCiAgICAgICAgeWxhYiA9ICJTbHVnZ2luZyBwZXJjZW50YWdlIiwNCiAgICAgICAgY29sID0gInJlZCIsDQogICAgICAgIGhvcml6b250YWwgPSBUUlVFKQ0KYGBgDQoNCg0KYGBge3J9DQpzYXBwbHkoaGl0dGVyczEsIG1lYW4sIG5hLnJtID0gVCkNCnNhcHBseShoaXR0ZXJzMiwgbWVhbiwgbmEucm0gPSBUKQ0Kc2FwcGx5KGhpdHRlcnMzLCBtZWFuLCBuYS5ybSA9IFQpDQpzYXBwbHkoaGl0dGVyczQsIG1lYW4sIG5hLnJtID0gVCkNCiNOb3RpY2UgdGhhdCBnaWdhbnRpYyBpbmNyZWFzZSBiZXR3ZWVuIGhpdHRlcnMyIGFuZCBoaXR0ZXJzMw0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShoaXR0ZXJzMSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaGl0dGVyczIpDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KGhpdHRlcnMzKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShoaXR0ZXJzNCkNCmBgYA0KDQpgYGB7cn0NCiNLZWVwIGJhdHRpbmcgc3RhdHMgdGhhdCB3ZSB3YW50IGZvciBwYWlycy4NCmJhdHRpbmdfbnVtIDwtIGJzdGF0cyAlPiUNCiAgZmlsdGVyKFBBID49IDE1MCkgJT4lDQogIHNlbGVjdCgiQkEiLCAnT0JQJywgJ1NsdWdQY3QnLCAiU08iLCAiQkIiLCAiSFIiKQ0KICANCmBgYA0KDQpgYGB7cn0NCnBhaXJzKGJhdHRpbmdfbnVtKQ0KYGBgDQojIyMjIENhcmVlciBCYXR0aW5nIFN0YXRzDQpgYGB7cn0NCmNhcmVlckJhdHRpbmcgPC0gbmEub21pdChic3RhdHMpDQpgYGANCg0KYGBge3J9DQpjYXJlZXJCYXR0aW5nIDwtIGNhcmVlckJhdHRpbmcgJT4lDQogIHNlbGVjdChwbGF5ZXJJRCwgQkEsIFBBLCBTbHVnUGN0LCBPQlAsIFNPLCBIUikgJT4lDQogIGdyb3VwX2J5KHBsYXllcklEKSAlPiUNCiAgc3VtbWFyaXNlX2FsbCgnbWVhbicpDQpgYGANCg0KYGBge3J9DQpjYXJlZXJCYXR0aW5nX251bSA8LSBjYXJlZXJCYXR0aW5nICU+JQ0KICBmaWx0ZXIoUEEgPj0gMTUwKSAlPiUNCiAgc2VsZWN0KEJBLCBQQSwgU2x1Z1BjdCwgT0JQLCBTTywgSFIpDQoNCnBhaXJzKGNhcmVlckJhdHRpbmdfbnVtKQ0KYGBgDQpgYGB7cn0NCmNvcnJtYXRyaXggPC0gY29yKGJhdHRpbmdfbnVtKQ0KY29ycnBsb3QoY29ycm1hdHJpeCwgbWV0aG9kID0gJ251bWJlcicpICNHaXZlcyB1cyBjb3JyZWxhdGlvbiBmcm9tIHBhaXJzIGdyYXBoLg0KYGBgDQoNCmBgYHtyfQ0KY2FyZWVyQmF0dGluZ19udW0xIDwtIGNhcmVlckJhdHRpbmdfbnVtICU+JQ0KICBmaWx0ZXIoUEEgPiA1MDApDQpgYGANCg0KDQojIyAwLWRpbWVuc2lvbmFsIFJlZHVjdGlvbiAoTGVzc29uIDQpDQoNCg0KIyMjIyBCb290c3RyYXBwaW5nDQoNCiMjIFBDQSAoTGVzc29uIDQpDQpgYGB7cn0NCnJlcyA8LSBiYXR0aW5nX251bSAlPiUgcHJjb21wKHNjYWxlID0gVFJVRSkNCnJlcw0KYGBgDQoNCmBgYHtyfQ0KbG9hZGluZ3MgPC0gcmVzJHJvdGF0aW9uDQpsb2FkaW5ncw0KYGBgDQoNCmBgYHtyfQ0Kc2NvcmVfbWF0IDwtIHJlcyR4DQpzY29yZV9tYXQNCmBgYA0KDQoNCmBgYHtyfQ0KZ2V0X2VpZyhyZXMpDQpgYGANCg0KIyMjIyBTY3JlZXBsb3QNCmBgYHtyfQ0KZ2V0X2VpZyhyZXMpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxOjYsIHkgPSBjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnQpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gODApICsNCiAgeGxhYigiUHJpbmNpcGFsIENvbXBvbmVudCIpICsNCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBWYXJpYW5jZSBFeHBsYWluZWQiKSArDQogIGdndGl0bGUoIlNjcmVlIFBsb3Qgb2YgUHJpbmNpcGFsIENvbXBvbmVudCBmb3IgQmF0dGluZyBTdGF0aXN0aWNzIikNCmBgYA0KDQoyIFByaW5jaXBhbCBDb21wb25lbnRzOiBQQzEgYW5kIFBDMg0KDQpgYGB7cn0NCmZ2aXpfc2NyZWVwbG90KHJlcywgbWFpbiA9ICJTY3JlZSBQbG90IikNCmBgYA0KDQpDYW4gSWRlbnRpZnkgYW4gZWxib3cgaW4gMy4NCg0KIyMjIyBCaXBsb3QNCmBgYHtyfQ0KcmVzICU+JQ0KICBmdml6X3BjYV92YXIoYXhlcyA9IGMoMSwyKSwNCiAgICAgICAgICAgICAgIGNvbC52YXIgPSAiY29udHJpYiIsDQogICAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwNCiAgICAgICAgICAgICAgIHJlcGVsID0gVFJVRQ0KICAgICAgICAgICAgICAgKQ0KYGBgDQoNCg0KIyMgQ2x1c3RlciBBbmFseXNpcyAoTGVzc29uIDUpDQpgYGB7cn0NCiNOT1QgQ09NUExFVEUhISEhISBUaGlzIHdhcyBqdXN0IGEgdGVzdCwgYnN0YXRzIGlzIHdheSB0b28gYmlnLg0KYnN0YXRzX2Jlc3QgPC0gYnN0YXRzICU+JQ0KICBmaWx0ZXIoUEEgPj0gNjAwKQ0KDQpldV9kaXN0IDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gJ2V1Y2xpZGVhbicpDQpgYGANCg0KYGBge3J9DQpoY19jb21wbGV0ZSA8LSBoY2x1c3QoZXVfZGlzdCwgbWV0aG9kID0gJ2NvbXBsZXRlJykNCg0KcGxvdChoY19jb21wbGV0ZSkNCmBgYA0KDQojIyMjIFNpbGhvdWV0dGUNCg0KYGBge3J9DQpyZXNfdGVzdCA8LSBjYXJlZXJCYXR0aW5nX251bTEgJT4lIGttZWFucyg3KQ0KICBzdHIocmVzX3Rlc3QpDQpgYGANCg0KDQpgYGB7cn0NCmRpc3RhbmNlIDwtIGdldF9kaXN0KGNhcmVlckJhdHRpbmdfbnVtMSwgbWV0aG9kID0gImV1Y2xpZGVhbiIpDQpzaWwgPC0gc2lsaG91ZXR0ZSh4ID0gcmVzX3Rlc3QkY2x1c3RlciwgZGlzdCA9IGRpc3RhbmNlKQ0Kc3VtbWFyeShzaWwpDQpzaWwgJT4lIGhlYWQoKQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9zaWxob3VldHRlKHNpbCkNCmBgYA0KDQpgYGB7cn0NCmZ2aXpfbmJjbHVzdChjYXJlZXJCYXR0aW5nX251bTEsIGhjdXQsIGhjX21ldGhvZCA9ICJjb21wbGV0ZSIsIGhjX21ldHJpYyA9ICJldWNsaWRlYW4iLCBtZXRob2QgPSAid3NzIikNCmBgYA0KDQpgYGB7cn0NCiMjVGhpcyBpcyB0byB0ZXN0IG90aGVyIHZhbHVlcyBvZiBLIGZvciB0aGUgc2lsaG91ZXR0ZSBtZXRob2QuDQpyZXNfdGVzdDEgPC0gY2FyZWVyQmF0dGluZ19udW0xICU+JSBrbWVhbnMoMTAgKQ0KICBzdHIocmVzX3Rlc3QxKQ0KYGBgDQoNCg0KYGBge3J9DQpkaXN0YW5jZSA8LSBnZXRfZGlzdChjYXJlZXJCYXR0aW5nX251bTEsIG1ldGhvZD0iZXVjbGlkZWFuIikNCnNpbCA8LSBzaWxob3VldHRlKHggPSByZXNfdGVzdDEkY2x1c3RlciwgZGlzdCA9IGRpc3RhbmNlKQ0Kc3VtbWFyeShzaWwpDQpzaWwgJT4lIGhlYWQoKQ0KYGBgDQoNCmBgYHtyfQ0KZnZpel9zaWxob3VldHRlKHNpbCkNCmBgYA0KDQoNCiMjIyMgRGlhbmENCg0KIyMgTGluZWFyIFJlZ3Jlc3Npb24gKExlc3NvbiA2KQ0KDQpMaW5lYXIgUmVncmVzc2lvbiBjb21wYXJpbmcgdGVhbSBwYXlyb2xsIGFuZCB3aW4gcmF0ZS4NCmBgYHtyfQ0KdGVhbXMgPSBhcy5kYXRhLnRhYmxlKFRlYW1zKQ0KdGVhbXMgPSB0ZWFtc1ssIC4oeWVhcklELA0KICAgICAgICAgICAgICAgICAgbGdJRCA9IGFzLmNoYXJhY3RlcihsZ0lEKSwNCiAgICAgICAgICAgICAgICAgIHRlYW1JRCA9IGFzLmNoYXJhY3Rlcih0ZWFtSUQpLA0KICAgICAgICAgICAgICAgICAgZnJhbmNoSUQgPSBhcy5jaGFyYWN0ZXIoZnJhbmNoSUQpLA0KICAgICAgICAgICAgICAgICAgUmFuaywgRywgVywgTCwgUiwgRVJBLCBTTywNCiAgICAgICAgICAgICAgICAgIFdpblBlcmNlbnQgPSBXLyhXK0wpKV0NCg0Kc2FsYXJpZXMgPSBhcy5kYXRhLnRhYmxlKFNhbGFyaWVzKQ0Kc2FsYXJpZXMgPSBzYWxhcmllc1ssIGMoImxnSUQiLCAidGVhbUlEIiwgInNhbGFyeTFNIikgOj0NCiAgICAgICAgICAgICAgICAgICAgICBsaXN0KGFzLmNoYXJhY3RlcihsZ0lEKSwgYXMuY2hhcmFjdGVyKHRlYW1JRCksIHNhbGFyeSAvIDFlNkwpXQ0KcGF5cm9sbCA9IHNhbGFyaWVzWywgLihwYXlyb2xsID0gc3VtKHNhbGFyeTFNKSksIGJ5PS4odGVhbUlELCB5ZWFySUQpXQ0KdGVhbVBheXJvbGwgPSBtZXJnZSh0ZWFtcywgcGF5cm9sbCwgYnkgPSBjKCJ0ZWFtSUQiLCAieWVhcklEIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHRlYW1QYXlyb2xsLCBhZXMoeCA9IHBheXJvbGwsIHkgPSBXaW5QZXJjZW50KSkgKyBnZW9tX3BvaW50KCkgICsgbGFicyh4ID0gIlBheXJvbGwgKGluIG1pbGxpb25zKSIsIHkgPSAiV2luIFBlcmNlbnRhZ2UiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBzZSA9IEZBTFNFKQ0KDQpgYGANCmBgYHtyfQ0KbW9kX2xtIDwtIGxtKGRhdGEgPSB0ZWFtUGF5cm9sbCwgV2luUGVyY2VudH5wYXlyb2xsKQ0KbW9kX2xtDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9sbSkNCmBgYA0KYGBge3J9DQpwYXlyb2xsX3ByZWQgPC0gdGVhbVBheXJvbGwgJT4lDQogIGFkZF9wcmVkaWN0aW9ucyhtb2RfbG0pDQoNCnBheXJvbGxfcHJlZCAlPiUNCiAgZmlsdGVyKHllYXJJRCA+PSAyMDEwKSAlPiUNCiAgYXJyYW5nZShkZXNjKHByZWQpKSAlPiUNCiAgaGVhZCgyNSkNCmBgYA0KYGBge3J9DQpwYXlyb2xsX3ByZWQgJT4lDQogIGZpbHRlcih5ZWFySUQgPj0gMjAxMCkgJT4lDQogIGFycmFuZ2UoZGVzYyhXaW5QZXJjZW50KSkgJT4lDQogIGhlYWQoMjUpDQpgYGANCk9ubHkgZml2ZSB0ZWFtcyBhcmUgaW4gdGhlIHRvcCAyNSBvZiBib3RoIHBheXJvbGwgYW5kIHdpbiBwZXJjZW50YWdlIGluIHRoZSAyMDEwcy4gVGhlc2UgdGVhbXMgYXJlIHRoZSAyMDExIFBoaWxsaWVzLCAyMDExIFlhbmtlZXMsIDIwMTAgWWFua2VlcywgMjAxMiBZYW5rZWVzLCBhbmQgMjAxNiBSYW5nZXJzLiBUaGlzIHNob3dzIHRoYXQgc3BlbmRpbmcgdGhlIG1vc3QgbW9uZXkgZG9lc24ndCBhdXRvbWF0aWNhbGx5IG1lYW4geW91IGFyZSBnZXR0aW5nIHRoZSBiZXN0IHByb2R1Y3Qgb24gdGhlIGZpZWxkLg0KIyMgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uDQoNCiMjIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uDQpgYGB7cn0NCmJzdGF0c19zYWxhcnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUNCiAgZmlsdGVyKFBBID49IDEwMCkgJT4lDQogIGZpbHRlcihzYWxhcnkgPiA1MDAwMDApDQpgYGANCg0KDQpgYGB7cn0NCmxtX21vZCA8LSBsbShzYWxhcnkgfiBILCBIUiwgZGF0YSA9IGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5KQ0Kc3VtbWFyeShsbV9tb2QpDQpgYGANCg0KYGBge3J9DQpsbV9tb2RfcHJkIDwtIGJzdGF0c19zYWxhcnlfMjFjZW50dXJ5ICU+JSBhZGRfcHJlZGljdGlvbnMobG1fbW9kKQ0KbG1fbW9kX3ByZA0KYGBgDQoNCmBgYHtyfQ0KZnVsbF9tb2RlbCA8LSBsbShzYWxhcnkgfi4sIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSkNCnN1bW1hcnkoZnVsbF9tb2RlbCkNCmBgYA0KDQpgYGB7cn0NCmZ1bGxfbW9kZWxfcHJlZCA8LSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgYWRkX3ByZWRpY3Rpb25zKGZ1bGxfbW9kZWwpDQpmdWxsX21vZGVsX3ByZWQNCmBgYA0KDQpgYGB7cn0NCmFkdl9zdGF0X21vZCA8LSBsbShzYWxhcnkgfiBPUFMsIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSkNCnN1bW1hcnkoYWR2X3N0YXRfbW9kKQ0KYGBgDQoNCg0KIyMgUmVzYW1wbGluZyBNZXRob2RzDQoNCmBgYHtyfQ0KI2luY2x1ZGluZyAyMDAyIGFuZCB1cCBiZWNhdXNlIHNhbGFyeSBiZWNvbWVzIGhpZ2hlcg0KYnN0YXRzX3NhbGFyeV8yMWNlbnR1cnkgPC0gYnN0YXRzX3NhbGFyeSAlPiUNCiAgZmlsdGVyKHllYXJJRCA+PSAyMDAyKQ0KYGBgDQoNCg0KYGBge3J9DQpic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgaGVhZCgxMCkNCmBgYA0KDQoNCg0KYGBge3J9DQojIHNldHRpbmcgc2VlZCB0byBnZW5lcmF0ZSBhIHJlcHJvZHVjaWJsZSByYW5kb20gc2FtcGxpbmcNCnNldC5zZWVkKDEyMykNCiANCiMgZGVmaW5pbmcgdHJhaW5pbmcgY29udHJvbCBhcyBjcm9zcy12YWxpZGF0aW9uIGFuZCB2YWx1ZSBvZiBLIGVxdWFsIHRvIDEwDQp0cmFpbl9jb250cm9sIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyID0gMTApDQoNCiMgdHJhaW5pbmcgdGhlIG1vZGVsDQptb2RlbCA8LSB0cmFpbihzYWxhcnkgfiBPQlAsIGRhdGEgPSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSwNCiAgICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbl9jb250cm9sKQ0KDQpwcmludChtb2RlbCkNCmBgYA0KDQoNCiMjIEZlYXR1cmUgU2VsZWN0aW9uDQpgYGB7cn0NCmJzdGF0c19zYWxhcnlfbnVtdmFycyA8LSBic3RhdHNfc2FsYXJ5XzIxY2VudHVyeSAlPiUgDQogIHNlbGVjdChjKDY6MzIpKQ0KYGBgDQoNCmBgYHtyfQ0KI0NvcnJlbGF0aW9uIG1hcHBpbmcgDQoNCiNtYWtpbmcgY29ycmVsYXRpb24gaGVhdCBtYXAgDQpjb3JyX251bWVyaWMgPC0gcm91bmQoY29yKGJzdGF0c19zYWxhcnlfbnVtdmFycyksIDEpDQoNCiNwbG90IHRvIHZpc3VhbGl6ZSB0aGUgY29ycmVsYXRpb25zIA0KZ2djb3JycGxvdChjb3JyX251bWVyaWMsDQogICAgICAgICAgIHR5cGUgPSAibG93ZXIiLA0KICAgICAgICAgICBsYWIgPSBUUlVFLCANCiAgICAgICAgICAgbGFiX3NpemUgPSAyLCAgDQogICAgICAgICAgIGNvbG9ycyA9IGMoInRvbWF0bzIiLCAid2hpdGUiLCAic3ByaW5nZ3JlZW4zIiksDQogICAgICAgICAgIHRpdGxlPSJDb3JyZWxvZ3JhbSBvZiBiYXR0aW5nIERhdGEiLCANCiAgICAgICAgICAgZ2d0aGVtZT10aGVtZV9idykNCmBgYA0KDQpgYGB7cn0NCnJlZ2ZpdC5mdWxsID0gcmVnc3Vic2V0cyhzYWxhcnkgfi4sIGRhdGEgPSBic3RhdHNfc2FsYXJ5X251bXZhcnMsICBudm1heCA9IDEzLCBtZXRob2Q9ImV4aGF1c3RpdmUiKQ0Kc3VtbWFyeShyZWdmaXQuZnVsbCkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkocmVnZml0LmZ1bGwpJHJzcQ0KYGBgDQoNCg0KDQpgYGB7cn0NCnBsb3Qoc3VtbWFyeShyZWdmaXQuZnVsbCkkcnNxKQ0KYGBgDQoNCmBgYHtyfQ0KcmVnLnN1bW1hcnkgPC0gc3VtbWFyeShyZWdmaXQuZnVsbCkgI2dldCB0aGUgc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygyLDIpKQ0KI3JzcyBwbG90IC0gIE5PVCBVU0VGVUwNCnBsb3QocmVnLnN1bW1hcnkkcnNzICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iUlNTIix0eXBlPSJsIikNCg0KI2FkanIyIHBsb3QNCnBsb3QocmVnLnN1bW1hcnkkYWRqcjIgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIiwgeWxhYj0iQWRqdXN0ZWQgUlNxIix0eXBlPSJsIikNCg0KbWF4X2FkanIyIDwtIHdoaWNoLm1heChyZWcuc3VtbWFyeSRhZGpyMikNCnBvaW50cyhtYXhfYWRqcjIscmVnLnN1bW1hcnkkYWRqcjJbbWF4X2FkanIyXSwgY29sPSJyZWQiLGNleD0yLHBjaD0yMCkNCg0KIyBBSUMgY3JpdGVyaW9uIChDcCkgdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkY3AgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJDcCIsIHR5cGU9J2wnKQ0KDQptaW5fY3AgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGNwICkNCnBvaW50cyhtaW5fY3AsIHJlZy5zdW1tYXJ5JGNwW21pbl9jcF0sY29sPSJyZWQiLGNleD0yLHBjaD0yMCkNCg0KIyBCSUMgY3JpdGVyaW9uIHRvIG1pbmltaXplDQpwbG90KHJlZy5zdW1tYXJ5JGJpYyAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IkJJQyIsdHlwZT0nbCcpDQoNCm1pbl9iaWMgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGJpYykNCnBvaW50cyhtaW5fYmljLHJlZy5zdW1tYXJ5JGJpY1ttaW5fYmljXSxjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KYGBgDQoNCmBgYHtyfQ0KI0ZvcndhcmQgc3RlcHdpc2Ugc2VsZWN0aW9uDQpyZWdmaXQuZndkID0gcmVnc3Vic2V0cyhzYWxhcnkgfi4gLCBkYXRhPWJzdGF0c19zYWxhcnlfbnVtdmFycywgbnZtYXg9MTMsIG1ldGhvZCA9ImZvcndhcmQiKQ0Kc3VtbWFyeShyZWdmaXQuZndkKQ0KYGBgDQoNCmBgYHtyfQ0KcmVnLnN1bW1hcnkgPC0gc3VtbWFyeShyZWdmaXQuZndkKSAjZ2V0IHRoZSBzdW1tYXJ5DQoNCnBhcihtZnJvdz1jKDIsMikpDQojcnNzIHBsb3QgLSAgTk9UIFVTRUZVTA0KcGxvdChyZWcuc3VtbWFyeSRyc3MgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJSU1MiLHR5cGU9ImwiKQ0KDQojYWRqcjIgcGxvdA0KcGxvdChyZWcuc3VtbWFyeSRhZGpyMiAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLCB5bGFiPSJBZGp1c3RlZCBSU3EiLHR5cGU9ImwiKQ0KDQptYXhfYWRqcjIgPC0gd2hpY2gubWF4KHJlZy5zdW1tYXJ5JGFkanIyKQ0KcG9pbnRzKG1heF9hZGpyMixyZWcuc3VtbWFyeSRhZGpyMlttYXhfYWRqcjJdLCBjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KDQojIEFJQyBjcml0ZXJpb24gKENwKSB0byBtaW5pbWl6ZQ0KcGxvdChyZWcuc3VtbWFyeSRjcCAseGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLHlsYWI9IkNwIiwgdHlwZT0nbCcpDQoNCm1pbl9jcCA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkY3AgKQ0KcG9pbnRzKG1pbl9jcCwgcmVnLnN1bW1hcnkkY3BbbWluX2NwXSxjb2w9InJlZCIsY2V4PTIscGNoPTIwKQ0KDQojIEJJQyBjcml0ZXJpb24gdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkYmljICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iQklDIix0eXBlPSdsJykNCg0KbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQ0KcG9pbnRzKG1pbl9iaWMscmVnLnN1bW1hcnkkYmljW21pbl9iaWNdLGNvbD0icmVkIixjZXg9MixwY2g9MjApDQpgYGANCg0KYGBge3J9DQojQmFja3dhcmRzIHN0ZXB3aXNlIHNlbGVjdGlvbg0KcmVnZml0LmJ3ZCA9IHJlZ3N1YnNldHMoc2FsYXJ5IH4uICwgZGF0YT1ic3RhdHNfc2FsYXJ5X251bXZhcnMsbnZtYXg9MTMsIG1ldGhvZCA9ImJhY2t3YXJkIikNCnN1bW1hcnkocmVnZml0LmJ3ZCkNCmBgYA0KDQpgYGB7cn0NCnJlZy5zdW1tYXJ5IDwtIHN1bW1hcnkocmVnZml0LmJ3ZCkgI2dldCB0aGUgc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygyLDIpKQ0KI3JzcyBwbG90IC0gIE5PVCBVU0VGVUwNCnBsb3QocmVnLnN1bW1hcnkkcnNzICx4bGFiPSJOdW1iZXIgb2YgVmFyaWFibGVzICIseWxhYj0iUlNTIix0eXBlPSJsIikNCg0KI2FkanIyIHBsb3QNCnBsb3QocmVnLnN1bW1hcnkkYWRqcjIgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIiwgeWxhYj0iQWRqdXN0ZWQgUlNxIix0eXBlPSJsIikNCg0KbWF4X2FkanIyIDwtIHdoaWNoLm1heChyZWcuc3VtbWFyeSRhZGpyMikNCnBvaW50cyhtYXhfYWRqcjIsIHJlZy5zdW1tYXJ5JGFkanIyW21heF9hZGpyMl0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkNCg0KIyBBSUMgY3JpdGVyaW9uIChDcCkgdG8gbWluaW1pemUNCnBsb3QocmVnLnN1bW1hcnkkY3AgLHhsYWI9Ik51bWJlciBvZiBWYXJpYWJsZXMgIix5bGFiPSJDcCIsIHR5cGU9J2wnKQ0KDQptaW5fY3AgPC0gd2hpY2gubWluKHJlZy5zdW1tYXJ5JGNwICkNCnBvaW50cyhtaW5fY3AsIHJlZy5zdW1tYXJ5JGNwW21pbl9jcF0sIGNvbD0icmVkIiwgY2V4PTIsIHBjaD0yMCkNCg0KIyBCSUMgY3JpdGVyaW9uIHRvIG1pbmltaXplDQpwbG90KHJlZy5zdW1tYXJ5JGJpYywgeGxhYj0iTnVtYmVyIG9mIFZhcmlhYmxlcyAiLCB5bGFiPSJCSUMiLCB0eXBlPSdsJykNCg0KbWluX2JpYyA8LSB3aGljaC5taW4ocmVnLnN1bW1hcnkkYmljKQ0KcG9pbnRzKG1pbl9iaWMsIHJlZy5zdW1tYXJ5JGJpY1ttaW5fYmljXSwgY29sPSJyZWQiLCBjZXg9MiwgcGNoPTIwKQ0KYGBgDQoNCmBgYHtyfQ0KI3JpZGdlIHJlZ3Jlc3Npb24gDQoNCiMgZ2V0dGluZyB0aGUgcHJlZGljdG9ycw0KeF92YXIgPC0gYnN0YXRzX3NhbGFyeV9udW12YXJzICU+JSBzZWxlY3QoLXNhbGFyeSkgJT4lIGFzLm1hdHJpeCgpDQojIGdldHRpbmcgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlDQp5X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnNbLCJzYWxhcnkiXQ0KYGBgDQoNCmBgYHtyfQ0KcmlkZ2UgPC0gZ2xtbmV0KHhfdmFyLCB5X3ZhciwgYWxwaGE9MCkNCnN1bW1hcnkocmlkZ2UpDQpgYGANCg0KYGBge3J9DQpjdl9yaWRnZSA8LSBjdi5nbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYSA9IDApDQpjdl9yaWRnZQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdChjdl9yaWRnZSkNCmBgYA0KDQpgYGB7cn0NCmN2X3JpZGdlJGxhbWJkYS5taW4NCmBgYA0KDQpgYGB7cn0NCmN2X3JpZGdlJGxhbWJkYS4xc2UNCmBgYA0KDQpgYGB7cn0NCmxic19mdW4gPC0gZnVuY3Rpb24oZml0LCBvZmZzZXRfeD0xLCAuLi4pIHsNCiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkNCiAgeCA8LSBsb2coZml0JGxhbWJkYVtMXSkgKyBvZmZzZXRfeA0KICB5IDwtIGZpdCRiZXRhWyAsTF0NCiAgbGFicyA8LSBuYW1lcyh5KQ0KICB0ZXh0KHgsIHksIGxhYmVscz1sYWJzLCAuLi4pDQp9DQoNCnBsb3QocmlkZ2UsIHh2YXIgPSAibGFtYmRhIiwgbGFiZWw9VCkNCmxic19mdW4ocmlkZ2UpICMgYWRkIG5hbW5lcw0KDQphYmxpbmUodiA9IGxvZyhjdl9yaWRnZSRsYW1iZGEubWluKSwgY29sID0gInJlZCIsIGx0eT0yKSAjbGFtYmRhLm1pbg0KYWJsaW5lKHYgPSBsb2coY3ZfcmlkZ2UkbGFtYmRhLjFzZSksIGNvbD0iYmx1ZSIsIGx0eT0yKSAgI2xhbWJkYS4xc2UNCmBgYA0KDQpgYGB7cn0NCm1pbl9yaWRnZSA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0wLCBsYW1iZGEgPSBjdl9yaWRnZSRsYW1iZGEubWluKQ0KY29lZihtaW5fcmlkZ2UpDQpgYGANCg0KYGBge3J9DQojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3QgZGF0YQ0KcHJlZGljdGlvbnMgPC0gbWluX3JpZGdlICU+JSBwcmVkaWN0KHhfdmFyKSAlPiUgYXMudmVjdG9yKCkNCg0KIyBNb2RlbCBwZXJmb3JtYW5jZSBtZXRyaWNzDQpkYXRhLmZyYW1lKA0KICBSTVNFID0gUk1TRShwcmVkaWN0aW9ucywgeV92YXIpLA0KICBSc3F1YXJlID0gUjIocHJlZGljdGlvbnMsIHlfdmFyKQ0KKQ0KYGBgDQoNCmBgYHtyfQ0KIyBMYXNzbyANCg0KIyBnZXR0aW5nIHRoZSBwcmVkaWN0b3JzDQp4X3ZhciA8LSBic3RhdHNfc2FsYXJ5X251bXZhcnMgJT4lIHNlbGVjdCgtc2FsYXJ5KSAlPiUgYXMubWF0cml4KCkNCiMgZ2V0dGluZyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUNCnlfdmFyIDwtIGJzdGF0c19zYWxhcnlfbnVtdmFyc1ssInNhbGFyeSJdDQpgYGANCg0KDQpgYGB7cn0NCmxhc3NvIDwtIGdsbW5ldCh4X3ZhciwgeV92YXIsIGFscGhhPTEpDQpzdW1tYXJ5KGxhc3NvKQ0KYGBgDQoNCmBgYHtyfQ0KY3ZfbGFzc28gPC0gY3YuZ2xtbmV0KHhfdmFyLCB5X3ZhciwgYWxwaGEgPSAxKQ0KY3ZfbGFzc28NCmBgYA0KDQpgYGB7cn0NCnBsb3QoY3ZfbGFzc28pDQpgYGANCg0KDQpgYGB7cn0NCmxic19mdW4gPC0gZnVuY3Rpb24oZml0LCBvZmZzZXRfeD0xLCAuLi4pIHsNCiAgTCA8LSBsZW5ndGgoZml0JGxhbWJkYSkNCiAgeCA8LSBsb2coZml0JGxhbWJkYVtMXSkrIG9mZnNldF94DQogIHkgPC0gZml0JGJldGFbLCBMXQ0KICBsYWJzIDwtIG5hbWVzKHkpDQogIHRleHQoeCwgeSwgbGFiZWxzPWxhYnMsIC4uLikNCn0NCnBsb3QobGFzc28sIHh2YXIgPSAibGFtYmRhIiwgbGFiZWw9VCkNCmxic19mdW4obGFzc28pDQoNCmFibGluZSh2PWxvZyhjdl9sYXNzbyRsYW1iZGEubWluKSwgY29sID0gInJlZCIsIGx0eT0yKQ0KYWJsaW5lKHY9bG9nKGN2X2xhc3NvJGxhbWJkYS4xc2UpLCBjb2w9ImJsdWUiLCBsdHk9MikNCmBgYA0KDQpgYGB7cn0NCm1pbl9sYXNzbyA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0xLCBsYW1iZGEgPSBjdl9sYXNzbyRsYW1iZGEubWluKQ0KY29lZihtaW5fbGFzc28pDQpgYGANCg0KYGBge3J9DQpzZV9sYXNzbyA8LSBnbG1uZXQoeF92YXIsIHlfdmFyLCBhbHBoYT0xLCBsYW1iZGEgPSBjdl9sYXNzbyRsYW1iZGEuMXNlKQ0KY29lZihzZV9sYXNzbykNCmBgYA0KDQpgYGB7cn0NCiMgTWFrZSBwcmVkaWN0aW9ucyBvbiB0aGUgdGVzdCBkYXRhDQpwcmVkaWN0aW9ucyA8LSBtaW5fbGFzc28gJT4lIHByZWRpY3QoeF92YXIpICU+JSBhcy52ZWN0b3IoKQ0KIyBNb2RlbCBwZXJmb3JtYW5jZSBtZXRyaWNzDQpkYXRhLmZyYW1lKA0KICBSTVNFID0gUk1TRShwcmVkaWN0aW9ucywgeV92YXIpLA0KICBSc3F1YXJlID0gUjIocHJlZGljdGlvbnMsIHlfdmFyKQ0KKQ0KYGBgDQoNCg0KDQojIyBTYWxhcnkgRGF0YQ0KYGBge3J9DQpmcmFuY2hpc2UgPC0gYyhgQU5BYCA9ICJMQUEiLCBgQVJJYCA9ICJBUkkiLCBgQVRMYCA9ICJBVEwiLCANCiAgICAgICAgICAgICAgIGBCQUxgID0gIkJBTCIsIGBCT1NgID0gIkJPUyIsIGBDQUxgID0gIkxBQSIsDQogICAgICAgICAgICAgICBgQ0hBYCA9ICJDSEEiLCBgQ0hOYCA9ICJDSE4iLCBgQ0lOYCA9ICJDSU4iLCANCiAgICAgICAgICAgICAgIGBDTEVgID0gIkNMRSIsIGBDT0xgID0gIkNPTCIsIGBERVRgID0gIkRFVCIsIA0KICAgICAgICAgICAgICAgYEZMT2AgPSAiTUlBIiwgYEhPVWAgPSAiSE9VIiwgYEtDQWAgPSAiS0NBIiwgDQogICAgICAgICAgICAgICBgTEFBYCA9ICJMQUEiLCBgTEFOYCA9ICJMQU4iLCBgTUlBYCA9ICJNSUEiLCANCiAgICAgICAgICAgICAgIGBNSUxgID0gIk1JTCIsIGBNSU5gID0gIk1JTiIsIGBNTDRgID0gIk1JTCIsIA0KICAgICAgICAgICAgICAgYE1PTmAgPSAiV0FTIiwgYE5ZQWAgPSAiTllBIiwgYE5ZTWAgPSAiTllOIiwgDQogICAgICAgICAgICAgICBgTllOYCA9ICJOWU4iLCBgT0FLYCA9ICJPQUsiLCBgUEhJYCA9ICJQSEkiLCANCiAgICAgICAgICAgICAgIGBQSVRgID0gIlBJVCIsIGBTRE5gID0gIlNETiIsIGBTRUFgID0gIlNFQSIsDQogICAgICAgICAgICAgICBgU0ZHYCA9ICJTRk4iLCBgU0ZOYCA9ICJTRk4iLCBgU0xOYCA9ICJTTE4iLCANCiAgICAgICAgICAgICAgIGBUQkFgID0gIlRCQSIsIGBURVhgID0gIlRFWCIsIGBUT1JgID0gIlRPUiIsDQogICAgICAgICAgICAgICBgV0FTYCA9ICJXQVMiKQ0KYGBgDQoNCmBgYHtyfQ0KU2FsYXJpZXMkZnJhbmNoaXNlIDwtIHVubmFtZShmcmFuY2hpc2VbU2FsYXJpZXMkdGVhbUlEXSkNCmBgYA0KDQoNCmBgYHtyfQ0KYXZnX3RlYW1fc2FsYXJpZXMgPC0gU2FsYXJpZXMgJT4lDQogICAgZ3JvdXBfYnkoeWVhcklELCBmcmFuY2hpc2UsIGxnSUQpICU+JQ0KICAgIHN1bW1hcmlzZShzYWxhcnkgPSBtZWFuKHNhbGFyeSkvMWU2KSAlPiUNCiAgICBmaWx0ZXIoIShmcmFuY2hpc2UgPT0gIkNMRSIgJiBsZ0lEID09ICJOTCIpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGF2Z190ZWFtX3NhbGFyaWVzLCANCiAgICAgICBhZXMoeCA9IHllYXJJRCwgeSA9IHNhbGFyeSwgZ3JvdXAgPSBmYWN0b3IoZnJhbmNoaXNlKSkpICsNCiAgICAgICBnZW9tX3BhdGgoKSArDQogICAgICAgbGFicyh4ID0gIlllYXIiLCB5ID0gIkF2ZXJhZ2UgdGVhbSBzYWxhcnkgKG1pbGxpb25zIFVTRCkiKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KFNhbGFyaWVzLCBhZXMoeCA9IGZhY3Rvcih5ZWFySUQpLCB5ID0gc2FsYXJ5LzFlNSkpICsNCiAgIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIG91dGxpZXIuc2l6ZSA9IDEpICsNCiAgIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJTYWxhcnkgKHBlciAkMSwwMDAsMDAwKSIpICsNCiAgIGNvb3JkX2ZsaXAoKQ0KYGBgDQpgYGB7cn0NCmF2Z190ZWFtX3NhbGFyaWVzMSA8LSBTYWxhcmllcyAlPiUNCiAgICBncm91cF9ieSh5ZWFySUQsIGZyYW5jaGlzZSwgbGdJRCkgJT4lDQogICAgc3VtbWFyaXNlKHNhbGFyeT0gbWVhbihzYWxhcnkpLzFlNikgJT4lDQogICAgZmlsdGVyKCEoZnJhbmNoaXNlID09ICJDTEUiICYgbGdJRCA9PSAiTkwiKSkgJT4lDQogICAgZmlsdGVyKHllYXJJRCA+PSAyMDAyKQ0KDQphdmdfdGVhbV9zYWxhcmllczEgJT4lDQogIGFycmFuZ2UoZGVzYyhzYWxhcnkpKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChhdmdfdGVhbV9zYWxhcmllczEsIGFlcyh4ID0gZnJhbmNoaXNlLCB5ID0gc2FsYXJ5KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHggPSAiVGVhbSIsIHkgPSAiU2FsYXJ5IChwZXIgJDEwMCwwMDApIikNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChhdmdfdGVhbV9zYWxhcmllczEsIGFlcyh4ID0gZnJhbmNoaXNlLCB5ID0gc2FsYXJ5LCBmaWxsID0gZnJhbmNoaXNlKSkgKw0KICAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDEpICsNCiAgIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJBdmVyYWdlIFRlYW0gU2FsYXJ5IFNpbmNlIDIwMDIgKHBlciAkMTAsMDAwLDAwMCkiKSArDQogICBjb29yZF9mbGlwKCkNCmBgYA0KDQo=
>>>>>>> c01ba71f4c47cfc4b1ae37e8d6b53559b193aeaf >>>>>>> 79253ef43377bff1d46431c2fb3c1c3a1085f815